Inspección de tráfico cifrado TLS/SSL

El incremento de la seguridad cifrando el canal de comunicación, no sólo dificulta las tareas a los “malos”, también nos complica saber qué están haciendo, a bajo nivel, nuestros programas cuando usan ese canal: el flujo de cliente contra un endpoint, consultas contra servicios externos, etc.

En este post trataremos de explicar cómo se puede capturar este tráfico y, lo más importante, cómo hacer que el tráfico cifrado se pueda volver legible.

Captura de tráfico

Cuando, aplicado a las comunicaciones, hablamos de capturar tráfico para ver qué está pasando en ellas, nos tiene que venir rápidamente a la mente la herramienta Wireshark.

Wireshark es un analizador de protocolos que, gracias a su GUI, nos presenta las comunicaciones a bajo nivel de una forma mucho más clara.

Tal como se observa en la siguiente captura, Wireshark muestra cada una de las interacciones que se hacen con los servidores, junto a una marca de tiempo, IP de origen, IP de destino, protocolo que se está capturando, datos que se envían, etc.

 

 

Esto cambia cuando se habilita el protocolo TLS. En este caso, nos encontramos a ciegas en la sección que corresponde a los datos que se están trasmitiendo, ya que van cifrados.

 

 

TLS/SSL Handshake en HTTPS

Antes de ver cómo podemos realizar debuging sobre este canal seguro, hay que echar una mirada por encima a cómo se establece y funciona una comunicación cifrada con TLS/SSL y cómo afecta al protocolo https u otros.

Cuando un cliente solicita una comunicación cifrada a un servidor web (https), éstos se tienen que poner de acuerdo en qué protocolo (SSL3, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3) y qué algoritmos criptográficos van a usar para autenticar, cifrar, realizar hash, etc. Ello provoca que haya más de cien combinaciones posibles. A esta fase de la comunicación se le llama TLS/SSL Handshake

Para comprobar desde el navegador cuáles son los protocolos y algoritmos seleccionados en el momento que se está viendo una página segura, se puede ir al icono de conexión segura  en la barra del navegador  y luego seleccionar detalles para mostrarlos.

Como ejemplo de estos protocolos y algoritmos, en la siguiente imagen se pueden observar los seleccionados por el navegador Firefox para acceder a la web duckduck.com:

 

Una de las formas de ver qué cifrados ofrece un servicio web es utilizando la herramienta testssl, a través del comando: testssl -­p <url>

Si quisiéramos ver los que ofrece google.es, emplearíamos testssl ­-p google.es, teniendo como salida:

 

Como se puede apreciar en la imagen anterior, hay un montón de algoritmos con siglas y números, que generan cientos de combinaciones. Pero, ¿cómo puedo ver lo que está pasando?

La mencionada mezcla de todos estos protocolos y algoritmos genera dos casos que harán que tengamos que actuar de una forma u otra para poder conseguirlo.

Que la comunicación esté cifrada usando las keys pública/privada o keys pública/privada más session keys. (¡Puff! Ahora le ha dado por hablar de keys…)

No desesperéis, de todo esto lo que tenéis que saber es si el servidor está ofreciendo Diffie-Hellman o no. Diffie-Hellman es un protocolo criptográfico usado para decidir qué keys simétricas de cifrado se van a usar para una comunicación.

Lo referenciaré como Metodo public/private key cuando NO use Diffie-Hellman y Metodo Session key cuando lo use.

Esta diferencia se puede ver en la negociación de algoritmos de cifrado que ofrece un servicio a través de la herramienta testssl.

Si en el campo KeyExch aparece ECDH o DH significa que se está ofreciendo Diffie-Hellman y, como es el sistema más seguro, será elegido de forma predeterminada sobre las otras opciones, siempre que el servidor y el cliente lo soporten, lo que llevará al uso de Session key. En caso que no se ofrezca, se aplicará el método de public/private key.

NOTA: A partir de la versión 1.2 de TLS, es cuando el cliente y el servicio negocian una key secreta simétrica común llamada master secret o session key.

Método Public/Private Key

Para esté método necesitaremos la private key del servicio. Con ella y con Wireshark ya no habrá tráfico cifrado con el servicio que se nos resista.

Aunque no es necesario, ya que se puede especificar directamente a Wireshark, es recomendable que le quitemos la contraseña que tenga para proteger la private key (normalmente en los servicios web no se configuran con contraseña ya que si se reinicia, el servicio no levantaría de forma automática).

Si tenemos el certificado en formato pkcs12 lo primero que tenemos que hacer es extraer la public key y la private key de la siguiente forma.

openssl pkcs12 in certificado.pfx ­-out private_nopass.key.pem ­
-nocerts ­-nodes

Luego quitaremos la contraseña de la private key. (Aunque parezca obvio, es necesario conocerla para poderla quitar 😉 )

openssl rsa -­in private.key.pem -­out private.key.pem

NOTA: Para poder usarse por Wireshark, es necesario que el formato sea pem.

 

Ahora pasamos a configurar Wireshark con la private key del servidor en el apartado correspondiente:

Wireshark > Edit > Preferences > Protocols > SSL > RSA Keys list > Edit > +

Nos aparecerá el siguiente desplegable, que tendremos que configurar de esta forma:

 

IP Address: IP del servidor al que pertenece la private key.

Port: Puerto que expone el servicio para ser consultado.

Protocol: Protocolo que se quiere analizar, para https será http, ya que es el protocolo encapsulado por TLS/SSL.

Key File: Path del fichero de la clave privada .pem.

Después de aceptar la anterior configuración, tendremos que reiniciar Wireshark para que actualice los cambios.

Cuando nos pongamos a capturar el trafico, con sacar el menú despegable Follow > TCP Stream sobre una de las capturas, podremos ver los datos sin cifrar.

 

Resumen del método:

  • No sirve cuando se usa cifrado Diffie-Hellman
  • Es soportado por todos los navegadores
  • Se necesita acceso al certificado del servidor

Método Session Key

Este método se puede hacer de dos formas, la primera implica aplicar restricciones sobre el protocolo de cifrado, mientras que, para la segunda, el protocolo se mantendrá completo y nos dará los datos necesarios para descifrar la comunicación (esta última forma mantiene el escenario más parecido a uno real).

Deshabilitando cifrado

Para deshabilitar el cifrado que usa session key, hay que eliminar del handsake la posibilidad de poder seleccionar el algoritmo Diffie-Hellman. Se puede eliminar tanto de la parte servidora como de la parte cliente.

La eliminación en el lado del cliente es mucho mas limpia y es la que se tendría que utilizar.

En caso de Firefox bastaría con:

  • Sacar la configuración del navegador, poniendo en la url about:config
  • Desactivar todas las entradas que contengan en el nombre de la preferencia que contengan la cadena DHE, esto se hará buscando DHE en el buscador y cambiando el campo valor a false.

 

En caso que de el cliente estuviera usando Java, se haría añadiendo jdk.TLS.disabledALGORITHMS=DHE, ECDHE en la parte relevante del código.

En otros lenguajes sería de forma parecida.

Para el lado del servidor, habría que buscar la configuración del servicio que permita restringir este algoritmo. Pero, insisto, éste es el método menos recomendado.

 

Sin deshabilitar cifrado

La segunda forma solo es compatible con los navegadores Chrome y Firefox, y es a través de la activación de una variable se sistema SSLKEYLOGFILE. Esta variable tendrá como valor un path completo a un fichero donde se guardará las sessionkeys.

Al arrancar el navegador, éste comprobará si está definida esta variable y, de ser así, guardará los valores de las session keys generadas para las sesiones TLS.

Pasos a seguir:

  • Configurar SSLKEYLOGFILE con el path del fichero.
export SSLKEYLOGFILE=/home/usuario/sessionkey.txt
  • Configurar Wireshark para que lea las session keys:

Edit > Preferences > Protocols > SSL > (Pre)-Master-Secret log filename > /home/usuario/sessionkey.txt > Aplicar

Con este método no hace falta tener la private key del servidor, ya que solo se usa al comienzo para asegurar la comunicación en el intercambio de las session keys.

 

Resumen del método:

  • Sirve cuando se usa cifrado Diffie-Hellman
  • No es necesario acceso a la private key del servidor
  • Solo puede ser activado en el lado del navegador

 

NOTA: Los métodos anteriores, funcionan tanto cuando el servidor es el único que presenta el certificado (siendo esto lo más habitual), como cuando se intercambian por parte del servidor y del cliente (autenticación mutua).

 

Bonus

Muchas veces nos encontraremos con que no podemos realizar la prueba desde un navegador web, a no ser que levantemos túneles a diestro y siniestro. Pero hay una alternativa si usamos curl, ya que desde la versión 7.57.0 nos permite sacar las session key. Esto también se aplica a los programas que usan las librerías libcurl, por lo que el abanico herramientas se amplía significativamente.

Hay que tener en cuenta que, para la versión 7.57.0, además de definir la variable SSLKEYLOGFILE, hay que añadir también la variable ENABLE_SSLKEYLOGFILE .

A partir de la 7.58.0 la variable ENABLE_SSLKEYLOGFILE ya viene definida por defecto y sólo se tendrá que definir SSLKEYLOGFILE.

Óscar Pérez

Desde que comencé con la informática me ha gustado llevar las máquinas al límite; ver con ojos curiosos las intrusiones y ataques, lo que hoy llamamos ciberseguridad. Soy curioso, trasteador nato, evangelizador de la seguridad, privacidad y las tecnologías en general.

More Posts