Copiar un certificado para evadir autenticación

En ocasiones, una aplicación web permite utilizar certificados X.509 como medio de autenticación. Estos certificados, asociados a una persona, pueden ser generados bien por una autoridad certificadora reconocida (FNMT, ACCV…), o de forma privada para uso interno de una organización. En cualquier caso, la aplicación web debería comprobar que el certificado que se presenta está firmado por la CA correspondiente. De esta forma, se está asegurando que la persona es quien dice ser. Para información más ampliada sobre infraestructuras PKI, podéis leer la estupenda serie de posts del compañero David Cutanda.

Ahora bien, es posible que el desarrollador de la aplicación no haya considerado necesario tomarse tanta molestia de comprobar firmas, y únicamente verifique que algún campo del certificado coincida con su base de datos, como el DNI, número de serie, etc. ¿Cómo podría un atacante aprovechar esa deficiencia? Generando un certificado con los mismos datos que un certificado válido, y rezando para que la aplicación no haga ninguna comprobación adicional, ya que la firma del certificado no coincide con la CA legítima.

Vamos al ajo. Supongamos que tenemos suficiente información sobre los certificados que se utilizan para la autenticación. Vamos a explicar los pasos para generar una CA con los mismos datos que la original, un certificado de un usuario, y después firmaremos ese certificado con la CA que hemos generado.

Crear clave privada RSA para la CA

$ openssl genrsa -out rootCA.key 2048

Crear CA

$ openssl req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem 
-subj "/O=Wayne Corp./OU=WaynePKI/CN=Wayne-CA"

Crear clave privada RSA para certificado personal

$ openssl genrsa -out personal.key 1024

Crear certificado

$ openssl req -new -key personal.key -out personal.csr -subj "/O=Wayne 
Corp./OU=Direccion/CN=Bruce Wayne" 

Firmar el certificado con la CA

$ openssl x509 -req -in personal.csr -CA rootCA.pem -CAkey rootCA.key -
CAcreateserial -out personal.crt -days 500 -set_serial 0x5599aaffbb4422cc

Exportar el certificado a PKCS12

$ openssl pkcs12 -export -out personal.p12 -in personal.crt -certfile rootCA.pem -
inkey personal.key

Exportar a PKCS12 es recomendable para poder importar el certificado en algún navegador. Es importante también darse cuenta que a la hora de firmar el certificado, es posible hardcodear el número de serie que deseemos. Si disponemos de un certificado legítimo que queramos clonar, se puede crear con el mismo número de serie. No es la primera vez que veo que ese dato es el que comprueba la aplicación para autenticarse.

En el caso de este ejemplo sólo he cumplimentado la organización O, unidad organizativa OU y common name CN, pero por supuesto se puede rellenar todo lo necesario para que el certificado sea lo más parecido posible al original.

Con el fichero personal.p12 generado ya podemos importarlo a nuestros navegadores, perfiles de SoapUI para auditar un WebService con WS-security, o lo que necesitemos. Es posible que también se necesite importar la CA que hemos creado al navegador como entidad de confianza, para que no se queje el navegador de que no puede comprobar la autenticidad del certificado.

¡A jugar!

Comments

  1. En definitiva, no utilizar los medios adecuados para comprobar la autenticidad de un certificado (tomando atajos) es como pegarse un tiro en el pie.
    Saludos