Marvin, el fallo criptográfico que nunca se arreglará

11 de octubre de 2023

Existe un fallo en el algoritmo fundamental de cifrado RSA desde hace 25 años, que reaparece de vez en cuando con diferentes nombres y formas. Llevan tres años analizando de nuevo el problema y han descubierto, entre otras cosas, que nunca se va a solucionar.

Para conseguirlo han tenido que realizar logros tan impresionantes como ser capaces de percibir cambios en el tiempo de procesamiento del orden de unos pocos ciclos de CPU de diferencia en la respuesta, a través de una red en producción a kilómetros saltando seis enrutadores en el camino. Lo han bautizado como Marvin.

En la novela “La guía del autoestopista galáctico” (de donde también sale el término “42”), Marvin es el Android que dura hasta el final del universo.

El fallo viene de 1998, cuando Daniel Bleichenbacher descubrió que los mensajes de error lanzados por servidores SSL al procesar el padding (relleno) del formato PKCS#1 (v1.5) permitían a atacantes descifrar la clave precompartida. Entender el fallo original no es tan difícil y ayuda mucho a ver por qué Marvin es un nuevo-viejo problema.

De dónde viene el problema con Marvin

PKCS#1 es un formato usado dentro del conjunto de algoritmos RSA que formatea los mensajes cuando son demasiados cortos. Para evitar que sea fácil descifrarlos, se hace “padding” o relleno. En SSL/TLS se envía un mensaje como clave de intercambio (pre shared key), que no es muy larga y por tanto debe rellenarse con padding hasta la longitud del módulo.

Si la pre-shared-key son 48 bytes, pues lo que quede hasta 256 bytes (clave de 2058 bits) es padding. Se rellena con esta información todo concatenado:

0x00 + 0x02 + números aleatorios siempre distintos de cero para rellenar + 0x00 + clave de intercambio.

El 0x00 y el 0x02 marcan el comienzo. El servidor SSL/TLS sabrá así que empieza el mensaje, que debe borrar todo hasta el cero y luego a partir del 0x00 se queda con lo que le interesa.

Para el ataque se usa el servidor SSL/TLS como oráculo. Se le bombardea constantemente con cadenas aleatorias y según su respuesta a si el padding es correcto o no, vamos adivinando datos. Esto fue el origen en el paper original de Bleichenbacher que describía “el ataque del millón de mensajes”.

Por cómo funciona RSA, el atacante debe despejar la m de esta ecuación

ms (mod n)

Donde s son los mensajes aleatorios que envía.

El “oráculo” servidor recibirá la cadena completamente aleatoria s como si estuviera cifrada, descifra con la clave que el servidor conoce pero nosotros no.

Si tenemos la suerte de que descifrando la s aleatoria, salga un 0x00, 0x02 al principio y luego un montón de datos aleatorios sin un cero, y después del 0x00 una cadena (algo que ocurrirá cada 30.000 o 130.000 intentos) el servidor responderá que está bien formateado, pero no está cifrado con la contraseña adecuada.

Y con esa respuesta binaria, aunque el mensaje no se haya descifrado bien del todo, el atacante habrá conseguido acotar mucho el rango de claves posibles.

Despejando la ecuación, el resultado de ms (mod n) estará en un rango muy concreto que el atacante podrá seguir acotando con más y más preguntas al servidor. Después de varios millones de preguntas, podría conocer la respuesta.

Pero, ¿qué pasa si el servidor no responde? ¿No hay oráculo? Es entonces cuando entra en juego los ataques de “side channel”.

Aunque no responda, puede haber milésimas de segundo de diferencia en su respuesta si, aunque incorrecto, el mensaje está bien formateado. Estas ligeras diferencias de tiempo le darán la pista. Este detalle es importante para entender Marvin.

Ataques sucesivos

Para contrarrestar este ataque, se hicieron otras mejoras en PKCS para que no se pudieran enviar datos completamente aleatorios, y el “padding” obedeciera a un hash circunstancial (RSA-OAEP). Pero con ligeras diferencias, el ataque seguía siendo posible gracias a los side channels de tiempo y que muchos servidores SSL todavía usan PKCS 1.5.

De hecho, en 2018 se descubrió una variante del ataque. Lo llamaron ROBOT, “the Return of Bleichenbacher's Oracle Threat”. Muchos servidores eran vulnerables. Se intentó arreglar, jugando con los tiempos. ROBOT demostró que la mitigación implementada para el fallo original, se implementó incorrectamente y todavía eran posibles ataques con los mismos fundamentos que el original.

Los sucesivos arreglos para que las ligeras diferencias de milisegundos en las repuestas del servidor no ayudaran al atacante, se creían suficientes. Pero no.

Marvin, este nuevo ataque que en realidad es básicamente el de ROBOT pero más preciso, ha venido a darle una vuelta de tuerca mayor. Sospechaban que desde 2020 el error seguiría ahí, y se comenzó una investigación que concluye que, gracias a la medición mucho más exhaustiva y una estadísticas más precisa, no hay solución, porque implementarla para “Marvin”, es todavía más complicado que ROBOT.

Ataques side channels por tiempo

Fundamentalmente, lo que han conseguido es ser muy precisos en los tiempos. No han inventado nada. Simplemente, se pensaba que los ataques por tiempo (de side channel) ya no eran posibles porque por insignificantes no darían pistas al atacante. Se llegó al consenso de que dejando las respuestas en el orden de nanosegundos, ya no se consideraría explotable.

Pero según los descubridores, no se estaba testeando bien. Tardaron tres años en aumentar la cantidad y precisión de las pruebas hasta poder percibir diferencias del orden de unos pocos ciclos de CPU de diferencia en la respuesta, a través de una red en producción a kilómetros saltando seis enrutadores en el camino. Todo gracias a la suficiente información disponible y con mejores técnicas estadísticas. Impresionante.

Por ejemplo, en GnuTLS se filtraba una diferencia de tiempo en la respuesta situada en otras partes del código (la que decidía qué tipo de error mostrar si el debug estaba activo). Implementar solución a esto implica modificar demasiado el software y en la práctica, imposible. Esos detalles imperceptibles han resucitado los side channel attacks que se creían muertos.

Por tanto, al descubrir que como no hay implementación posible que sea “side channel free”, cualquier cosa que use padding en RSA con PKCS#1 v1.5 podría ser susceptible de ser atacada con este nuevo método. Afecta a casi todo: OpenSSL, GnuTLS, NSS de Mozilla (incluso después del parche, según el descubridor), M2Crypto…

¿Solución?

Dejar de usar PKCS#1 en RSA para TLS (TLS 1.3 ya lo hace, abandona todo padding en lo posible después de muchos parches en sus versiones anteriores).

Hoy en día es también posible pasarse a ECDSA en vez de RSA.

Cuatro hitos en Ciberseguridad que marcaron el futuro del malware

Imagen de Fabrikasimf en Freepik.