Español | English
rss facebook linkedin Twitter

Drown a fondo: Un nuevo ataque al SSL. (PARTE II)


En este segundo post seguimos describiendo el ataque DROWN. Más información sobre este ataque puede encontrarse en el siguiente artículo: https://drownattack.com/drown-attack-paper.pdf

En el post anterior llevamos a cabo un análisis del protocolo de negociación de las diferentes versiones SSL/TLS. Vimos cómo dicho protocolo es diferente entre las versiones SSLv2 y las versiones superiores (SSLv3/TLS), e identificamos un valor concreto de 48 bytes de la negociación SSLv3/TLS (pre-master-secret) que de alguna forma pensamos que podemos descifrar sin necesidad de conocer la clave privada, engañando a un servidor SSLv2 que use la misma clave RSA. El siguiente paso a dar era convertir este pre-master-secret en un mensaje que el servidor SSLv2 identifique como un master-key válido y vimos que no era posible recortar a lo bruto el mensaje.

¿Cómo podemos continuar?
La respuesta se encuentra en el cifrado homomórfico. Este tipo de cifrado ya ha sido descrito por otro compañero en este mismo blog. Básicamente un algoritmo de cifrado homomórfico es aquél en el que se puede realizar cualquier operación entre dos mensajes cifrados sin necesidad de descifrarlos. Este tipo de algoritmos realmente no son usables actualmente debido a que la complejidad de las operaciones que hay que realizar sobre los datos cifrados para efectuar lo que en esencia es una suma o multiplicación sobre los datos originales es muy grande (aunque viene reduciéndose de forma notable en los últimos años).

Esta explicación está muy bien, pero no parece acercarnos al objetivo de transformar el pre-master-secret en un master-key. El detalle radica en que RSA es lo que se conoce como parcialmente homomórfico. Es decir, permite un número limitado de operaciones sobre los datos cifrados que llevan a modificaciones concretas en los datos originales. Si tenemos dos mensajes m1 y m2, y definimos E(x) como la operación de encriptar el mensaje x, entonces se da:

E(m1) * E(m2) = E(m1 * m2)

Donde * no es una multiplicación normal, sino una multiplicación en aritmética modular (en RSA todos los mensajes, tanto el mensaje original como el cifrado se tratan como números enteros). Por tanto, dado un valor al que llamamos m0, y del que únicamente se conoce su valor cifrado, al que llamamos c0, el objetivo es encontrar un número s tal que al multiplicar su valor cifrado por c0 nos devuelva un valor al que llamaremos c1, correspondiente a un m1 que es el resultado de multiplicar m0 por s. Es decir, operando con el valor cifrado conseguimos modificar a nuestro gusto el valor original.

En concreto, podemos pensar que m0 es el pre-master-secret que hemos capturado de la comunicación SSLv3/TLS, y el objetivo es descubrir un valor s tal que nos lo convierta en un m1 que sea adecuado para actuar como master-key en la negociación SSLv2:

E(s) * c0 = E(s) * E(m0) = E(s * m0) = E(m1) = c1



Es decir, ahora en la comunicación SSLv2 el atacante escoge un valor s al azar y envía dentro del mensaje ClientMasterKey el valor c1 con la esperanza de que sea un master-key válido (recordemos que la operación se hace a ciegas, sin conocer el valor real de m1), sabiendo que su mensaje descifrado m1 está relacionado con m0 (que recordemos que es el objetivo final) a través de s.

Desafortunadamente para el atacante, si nos fijamos en la negociación de SSLv2, justo después de mandar el paquete ClientMasterKey, debe enviar un paquete ClientFinished. En este paquete se debe enviar el identificador de conexión enviado por el servidor en ServerHello, cifrado con una de las claves simétricas que se han calculado a partir de los tres valores anteriores (en concreto la denominada client-write-key). Como el atacante no dispone del master-key (es lo que intenta descubrir para poder derivar el pre-master-secret de SSLv3/TLS), no puede calcular client-write-key y por tanto no puede enviar un paquete ClientFinished válido.

Afortunadamente para el atacante, tras enviar el paquete ClientMasterKey y mientras está pensando cómo demonios cifrar el contenido de ClientFinished, recibe inesperadamente un mensaje ServerVerify sin necesidad de hacer nada.

¿Qué ha ocurrido? 
Aunque en los ejemplos que aparecen en la especificación de SSLv2 el proceso seguido es el mostrado anteriormente, la especificación del paquete ServerVerify es ambigua, ya que en ningún momento especifica que se deba esperar al paquete ClientVerify, sino que dice que debe enviarse tras recibir el ClientMasterKey y disponer por tanto de todos los datos necesarios para generar las claves simétricas. En concreto, parece ser que todas las implementaciones de SSLv2 se basan en esta frase en vez de basarse en los ejemplos de flujo de paquetes. Por tanto, aunque el atacante no envíe su ClientVerify (como hemos dicho antes no puede calcularlo), el servidor sí envía su ServerVerify.

Es decir, el flujo real en este caso es:




El hecho de que el servidor haya generado una clave server-write-key a partir del valor c1 que el atacante ha enviado hace pensar que el ataque va por buen camino, ya que el atacante ha conseguido encontrar un valor de s correcto a la primera. Una suerte increíble. En este punto el atacante cierra la conexión porque ya tiene toda la información que podía sacar de esta negociación: el paquete ServerVerify. Este paquete contiene el valor "challenge" enviado por el cliente en ClientHello, cifrado con la clave server-write-key. Es decir, el servidor ha descifrado ClientMasterKey y lo ha usado para generar una clave con la que ha cifrado un valor que el atacante conoce.

El siguiente paso es descubrir el valor de server-write-key, para intentar inferir cuál es el master-key que hemos enviado al servidor. La solución pasa por la fuerza bruta.  Recordemos que en el primer post decíamos que el master-key estaba "parcialmente encriptado", de tal forma que en ciertas circunstancias una parte del master-key lo puede enviar el atacante en claro, fijando el valor como mejor le interese, y el mensaje c1 representa únicamente la parte cifrada del master key. 

En concreto, si el atacante negocia un algoritmo de cifrado EXPORT, el tamaño de la parte cifrada del master-key es de 40 bits y por tanto el atacante sólo tiene que probar un máximo de 240 valores diferentes de master-key hasta conseguir encontrar uno con el que calcula como server-write-key una clave que le permite descifrar el dato devuelto en ServerVerify  y obtener el "challenge" enviado inicialmente. Por tanto, el valor asignado a la parte cifrada del master-key es el valor de m1. Con esto y como m1 y m0 están relacionados a través de s, puede calcular m0, que era el pre-master-secret de la comunicación SSLv3/TLS y con los tres valores conocidos, ya puede calcular las claves simétricas y descifrar la comunicación, ¿verdad?

Pues la respuesta es que no... Ya sería casualidad que a la primera el atacante encontrara un s que le convierta un valor m0 de 48 bytes en un valor m1 de 5 bytes (los 40 bits cifrados del master-key en los algoritmos EXPORT). En realidad, lo más probable es que el m1 que ha utilizado vuelva a tener una longitud incorrecta (la probabilidad de que un valor s al azar nos devuelva un m1 válido es inferior a 1 entre 33 millones). Lo que ocurre es que la mayoría de las implementaciones actuales de SSLv2 (qué irónico es llamar "actual" a una implementación de SSLv2) incluyen protección contra un ataque conocido como el oráculo de Bleichenbacher. Un servidor que reciba un master-key de longitud incorrecta genera aleatoriamente un master-key y lo usa en lugar del enviado por el cliente, pero continúa todo el procesamiento igual. Como se asume que el cliente no será capaz de derivar la clave correcta (ya que no conoce el master-key usado por el servidor), la comunicación será incorrecta y finalizará.

Teniendo en cuenta que cada mensaje probado implica hasta 240 operaciones de descifrado para obtener la clave por fuerza bruta,  es necesario mejorar drásticamente las probabilidades de encontrar un m1 válido. 

Esto es algo que queda para nuestro tercer post.


Ion Larrañaga 
Software Innovation S21sec

(+34 902 222 521)


24 horas / 7 días a la semana



© Copyright S21sec 2013 - Todos los derechos reservados


login