Perfect Forward Secrecy: ¿Existe el secreto perfecto y permanente?

lunes, 19 de mayo de 2014

El atacante se dedicaba a "esnifar" conversaciones en redes internas, a través de cualquier técnica que le permitiera obtener el tráfico de sus víctimas. Para el tráfico cifrado, no sustituía certificados ni usaba sslstrip o cualquier otro método que pudiera poner en guardia al espiado. Simplemente atrapaba y almacenaba el tráfico cifrado por SSL. "Algún día esto podría serme útil", pensó. Hasta que llegó el 7 de abril de 2014. Entonces desempolvó varios gigabytes de información y sonrió. ¿Tenía motivos?

Ese día se dio a conocer Heartbleed y se demostró que era posible obtener la clave privada TLS/SSL de los servidores. Si se daba prisa, podría obtener las claves de los lugares vulnerables más populares, y con ella, descifrar todo el tráfico esnifado días o años atrás. Solo tendría que arrancar Wireshark, indicar en la configuración la clave privada robada gracias a Heartbleed, y cargar el tráfico cifrado que obtuvo en su día... ¿O no?

No tan rápido. Las bases del cifrado

RSA es un algoritmo de firma digital, creación de claves... y también de criptografía asimétrica. Diffie-Hellman es solo un algoritmo de intercambio de claves secretas en un entorno en el que un atacante podría tener acceso al canal de comunicación. Pero con la criptografía asimétrica (RSA), en realidad, también es posible intercambiar información por un canal inseguro: basta calcular una clave aleatoria, cifrarla con la clave pública del receptor y este la descifraría con su clave privada. Así intercambian y comparten clave y con ella cifrarían de forma simétrica la conversación.

Con estas dos filosofías "presentes", SSL/TLS puede ser implementado de muchas formas, y todo depende de la suite de cifrado que utilice el servidor. Veamos: En una conversación SSL/TLS "típica con RSA", el servidor se autentica a sí mismo (muestra su certificado y el cliente lo valida) y luego ambos acuerdan cifrar la conversación. En resumen (aunque hay una master y una premaster) los servidores cifran una contraseña y se la intercambian. Si un atacante robase la clave privada del servidor, podría descifrar todas las conversaciones pasadas, porque podría obtener la premaster key, deducir de ella la master y tener el tráfico en claro.

En este esquema el fallo es que se usa la clave privada del servidor (que es permanente hasta que caduque el certificado) tanto para autenticarse como para cifrar. Por tanto, en este entorno donde se utiliza RSA y cifrado asimétrico, descifrar conversaciones retroactivamente sería posible una vez obtenida la clave privada (gracias a Heartbleed, por ejemplo). La ciphersuite usada en el servidor sería, por ejemplo RSA_WITH_AES_256_CBC_SHA y sus combinaciones (RSA_WITH_RC4, RSA_WITH_AES_128....)

Pero no todos los servidores funcionan así, todo depende de la suite de cifrado. La solución para evitar ese descifrado retroactivo es usar una clave permanente (en el certificado) para autenticar, y otras efímeras (calculada al vuelo) para cifrar. ¿Cómo?

Separar autenticación y cifrado

RSA se puede seguir usando para autenticar, pero el intercambio de claves para el cifrado puede hacerse con Diffie Hellman (DH), que para eso es un algoritmo de intercambio de claves. Como matemáticamente sus valores son aleatorios y se usan una sola vez, se llaman efímeros (DHE). A su vez hay dos formas de implementar Diffie Hellman.
Esquema de funcionamiento de Diffie-Hellman.
Fuente: Wikipedia.

  • Con número discretos. Con un rendimiento peor.
  • Con curvas elípticas (ECDHE). Se consigue una seguridad muy buena con números más pequeños, y por tanto el rendimiento no decae tanto. Lo malo es que no todos los navegadores lo soportan. Una idea de lo reciente que es, es que openSSL lo implementó en su versión 1.0.0. 
A este uso de intercambio de claves efímeras (normalmente con DH en el contexto de SSL), se llama Perfect Forward Secrecy (PFS). Las cipher suites usadas en los servidores, serían por ejemplo DHE_RSA_WITH_DES_CBC_SHA y sus múltiples variantes.

Nada impide usar claves RSA "efímeras" para intercambiar una clave maestra con la que cifrar la información. De hecho se hacía antes (con TLS 1.0). Pero es lento en comparación con DHE. Y tenía un problema adicional precisamente por ser lento... para ahorrar tiempo, se generaban al vuelo claves RSA muy cortas, de forma que con el tiempo podrían llegar a ser rotas por fuerza bruta.

¿Entonces se puede ser descifrar retrospectivamente o no?

Será más fácil o no dependiendo de la suite de cifrado usada en el servidor. Pero en realidad, lo más probable es que el atacante descrito arriba, pueda seguir sonriendo. Aunque el servidor hubiera tomado la precaución (y las molestias, porque no es muy soportado, requiere software moderno, etc) de utilizar PFS, todavía habría una oportunidad para el atacante. SSL cuenta con dos sistemas para "acortar" el tiempo de handshake cuando un cliente se conecta a un servidor. Memoriza sus estados y consigue así una conexión más rápida, facilita el single-sing-on, etc. Estos mecanismos son:

  • Sessions IDs: Tanto servidor como cliente recuerdan sus estados, y ambos se comunican con un ID que identifica ese estado. El cliente lo usa para indicarle al servidor que "busque" en memoria la conexión de ese cliente concreto. El problema es que si hay muchos front-ends, cada servidor puede haber ofrecido un ID diferente al cliente, y para solucionarlo se deben guardar en disco y compartirlo, cosa que no es buena idea. Si por el contrario estos IDs se mantienen en memoria, rotan a menudo.
  • Session tickets: Con este método (activo por defecto en OpenSSL), es el servidor el que firma y envía el estado cifrado al cliente, y "se olvida". Un cliente toma un ticket de sesión de un servidor, y una vez validado, le puede servir para otro front-end diferente (en un cluster, por ejemplo) y no tener que empezar de nuevo. Esos tickets son como una especie de pases temporales de sesión que ahorran tiempo a todos. Se generan y se cifran independientemente, y, por la forma que trabaja TLS, su fortaleza es menor (utiliza un cifrado más débil). Así que, en cierta medida, si se usan tickets de sesión, el secreto es tan fuerte como el del cifrado durante el intercambio de estos tickets, no el del cifrado de la información "real". Y lo que es peor, la información para cifrar los tickets no rota demasiado. Se suelen generar en memoria del servidor. Si es un solo servidor SSL el que maneja toda la información, este puede mantener el mismo ticket de sesión desde que arranca el servicio en memoria hasta que sea reiniciado.


RFC sobre session tickets. Fuente: tools.ietf.org/html/rfc5077

Por tanto, si con Heartbleed se obtuvo un ticket de sesión además de la clave privada, es posible que se pudiera obtener toda la información cifrada con los tickets, y con ella deducir las conversaciones durante la validez de ese ticket... que podrían haber sido días y días atrás.

Sergio de los Santos
ssantos@11paths.com

No hay comentarios:

Publicar un comentario en la entrada