Disputa por vulnerabilidad CVE-2014-2734

Recientemente fuimos informados de una posible vulnerabilidad de seguridad que ha sido publicada como CVE-2014-2734. Sin embargo, basados en un análisis detallado, no consideramos que Ruby sea vulnerable.

Esta vulnerabilidad podría permitir a cualquier atacante a crear certificados raíz arbitrarios modificando la firma de el certificado y remplazando la llave privada del certificado original con cualquier otra elegida por el atacante.

Prueba de el concepto

A continuación veremos nuestro análisis de CVE-2014-2734 en una versión reducida, pero que creemos captura la esencia de el análisis original:

require 'openssl'

forge_key = OpenSSL::PKey::RSA.new(2048)
raw_certificate = File.read("arbitrary.cer")
cert = OpenSSL::X509::Certificate.new(raw_certificate)
resigned_cert = cert.sign(spoof, OpenSSL::Digest::SHA1.new)

resigned_cert.verify(key) #=> true

Puede que sea una sorpresa que X509Certificate#verify regresa true. El certificado original puede contener información de la llave pública que apunta a la llave pública original la cual es diferente a la llave pública de forge_key. Claramente, el par público / privado que fue usado para firmar de nuevo el certificado no concuerda con la llave pública referenciada en la información original. Entonces, ¿Por qué #verify regresa true?

Como es que las llaves son verificadas

X509Certificate#verify utiliza la función de OpenSSl X509_verify internamente, la cual delega a ASN1_item_verify. Estas funciones establecen la validez de la firma de acuerdo a la llave pública que fue presentada. Sin embargo, no verifican si la llave concuerda con alguna llave pública referenciada en el certificado. Esto significa que regresar true es comportamiento deseado para X509Certificate#verify en este escenario. Omitir esta verificación no tiene impacto significante en el modelo de seguridad de confianza X.509.

La sección 4.1.1.3 del RFC 5280 explícitamente dice que al procesar la firma de algún certificado, la CA confirma que la información que contiene el certificado sea correcta. Aunque este principio es violado en el código de ejemplo, esto no presenta una amenaza a la seguridad. Un certificado falso o modificado de esta manera no puede ser explotado a menos que alguien pueda convencerte de que explícitamente confíes en un certificado que viola este principio.

Riesgos Potenciales

Existen dos casos a considerar:

Volver a firmar un certificado de raíz

Como usuarios, confiamos en los certificados de raíz incondicionalmente. Incluso si no contienen información válida, el estado de ser un certificado de raíz reconocido públicamente es lo que los mantiene originales. Son valores preconfigurados en los almacenamientos de confianza de nuestros navegadores y sistemas operativos. Simplemente teniendo acceso a ellos establece su estado como anclas válidas de confianza. Por ejemplo, OpenSSL no revisa la firma de los certificados de raíz firmados por uno mismo por defecto por las mismas razones. X509_V_FLAG_CHECK_SS_SIGNATURE documentation.

Un certificado de raíz que ha sido firmado de nuevo, se convierte por defecto en un certificado “auto-firmado” (por lo tanto con información incorrecta de llave pública). Esto no es más peligroso que un certificado de raíz “auto-firmado” normal. De hecho, cualquiera puede crear certificados de raíz auto-firmados los cuales pueden concordar con aquel de un certificado de raíz valido, excepto por la firma. Como confiamos en los certificados de raíz simplemente por poseerlos, cualquier certificado impostor carece de valor sin que el cliente activamente decida confiar en el.

Firmado de un certificado intermedio

Tampoco volver a firmar un certificado que no es de raíz viola la seguridad de el sistema de confianza X.509. Aunque no tenemos en nuestro poder este tipo de certificados por adelantado, su validez puede ser comprobada durante el proceso de validación. La firma de cualquier certificado que no es de raíz es verificada utilizando la llave publica de el certificado que lo expidió. Si este es falso, en algún momento de la cadena de certificados será detectado como un valor de firma de certificado inválida.

Conclusión

En conclusión, creemos que X509Certificate#verify funciona como es debido.

Otros han llegado a la misma conclusión y por lo tanto hemos disputado el CVE-2014-2734 y pedido su cancelación. Puedes encontrar nuestro análisis completo de la prueba de concepto original aquí incluyendo algunos comentarios adicionales.