miércoles, 5 de marzo de 2014

GnuTLS goto fail... también

Nikos Mavrogiannopoulos, del equipo de seguridad de Red Hat, ha descubierto y parcheado una vulnerabilidad en la implementación de TLS (GnuTLS) que permitiría hacer pasar por válido un certificado falso.

TLS (Transport Layer Security) es el protocolo seguro de transporte llamado a suceder a SSL (Secure Socket Layer). Es uno de los pilares sobre el que se sustenta la seguridad de los datos cuando viajan a través de la red. Se da la circunstancia, tal y como comentamos anteriormente en Una-al-día, que hace varios días se descubrió un error similar en la implementación de TLS propia de Apple en la cual un infame 'goto fail' duplicado provocaba el mismo impacto que el fallo actual.

La repercusión de este tipo de errores es tremenda. Por hacer un símil, es como si en el puesto fronterizo de un país, pongamos Arstotzka, nos pidieran el pasaporte y diesen por valido una hoja de papel con un garabato. Hablamos por supuesto de autenticación. No se trataría de un fallo en el cifrado que debilitase el canal seguro o que facilite el descifrado en una captura del tráfico de red (normalmente este tipo de fallos son causados por la especificación). Se trata de la incapacidad de confiar en la autenticidad de un servidor. Situémonos en un escenario.

Supongamos que un director de I+D de cualquier compañía se encuentra sentado en la sala VIP de un aeropuerto, levanta la tapa de su portátil y ve dos puntos de acceso WiFi, "ViP WiFi" y "ViP WiFi 2". No se lo piensa dos veces, el segundo tiene mejor potencia, tanta que pareciera que el joven que se sienta frente a él tuviese escondido un punto de acceso portátil en su maletín. Se conecta, abre el navegador y se dirige a ver su webmail. Sabe que su conexión es segura y el sitio autentico, porque como le dijeron en el curso de concienciación "Hay que vigilar que la url empiece por HTTPS y todo esté en verde".

Y lo está, solo que ni la conexión WiFi es la del aeropuerto, ni el dominio lleva a la IP correcta, ni el certificado es válido. Sin embargo, como lo parece, sus claves, sus correos, sus pdf con documentación secreta, viajaran desde su ordenador hasta el chico del maletín y de ahí a un servidor que se conectará a su vez al servidor de la empresa...

GnuTLS se usa en muchos sistemas Linux y a su vez, en cientos de paquetes de estos sistemas. Esta vulnerabilidad es transversal, toda aplicación que compile contra esta librería es vulnerable. Como podemos ver en el parche aplicado
se han eliminado las líneas que contenían la instrucción "goto cleanup" en ciertas comprobaciones y se ha introducido, esta vez con relativo buen criterio, un "goto fail". La etiqueta "fail" da el valor '0' a la variable "result" que se usa, a su vez, en la etiqueta "cleanup".

Si observamos el código completo del archivo lib/x509/verify.c

Vemos que la variable "result" se usa para recoger el resultado de la función "_gnutls_x509_get_data". Dicha función (lib/x509/common.c) se invoca para leer datos firmados en formato DER (Distinguished Encondig Rules) de un certificado. Esta lectura se aloja en el puntero a estructura "gnutls_datum_t * signed_data", su último parámetro y devuelve 0 si la operación se ha efectuado con éxito. "gnutls_datum_t" es una estructura muy simple, un puntero a char y un entero donde se guarda el tamaño de la reserva de memoria apuntada.

"_gnutls_x509_get_data" se usa consecutivamente para recoger los valores del certificado y del certificado del emisor en las estructuras nombradas:

issuer_signed_data
cert_signed_data

De forma similar, tenemos la función "_gnutls_x509_get_signature" que obtendrá con parecido mecanismo las firmas del certificado y emisor sobre las estructuras:

issuer_signature
cert_signature

Estas comprobaciones se hacen dentro de la función "check_if_ca" usada para comprobar si el emisor de un certificado es una autoridad de certificación o el certificado es el mismo que el del emisor, dentro del contexto de la cadena de certificados. Varias líneas más abajo, también se parchea otra variable "result", local a la función "_gnutls_verify_certificate2", que a su vez llama a "check_if_ca" y se usa para comprobar el certificado contra una lista de autoridades certificadoras de confianza (las que tenemos en el sistema). También hace uso de similares comprobaciones como las comentadas arriba.

Da la impresión de que es posible manipular un certificado desde varios campos distintos y no solo desde uno. También que el fallo estaría relacionado con la circunstancia de que el certificado y el del emisor sea el mismo.

Viendo el parche, podemos observar la importancia de comprobar el estado de las variables tras las comprobaciones y sus valores por defecto cuando estas son declaradas.

La vulnerabilidad con CVE-2014-0092 ya ha sido arreglada y se espera que se propague a todas las distribuciones a través de sus sistemas de paquetes.

Más información:

corrected return codes

una-al-dia (25/02/2014) Actualización de Apple para iOS 6 y 7




David García
Twitter: @dgn1729

3 comentarios: