viernes, marzo 20, 2015

Un HASH MD5 en la password no sustituye a SSL

En muchas auditorías de nuestro servicio de Pentesting Persistente Faast nos hemos encontrado con paneles de login que utilizan elementos criptográficos diseñados por ellos para securizar el envío de credenciales por la red. Inventar sistemas de estas características cuando ya hay sistemas de cifrado de comunicaciones digitales probados y testados, no suele ser una buena idea. Hay que decir que en ocasiones esto se hace para evitar el despliegue de un sistema de SSL, y por tanto, además, estas conexiones viajaban por el protocolo HTTP, lo que permite que simplemente con un sniffer se puedan obtener los datos necesarios para descifrar la información que es enviada. Uno de los casos con los que nos encontramos auditando fue, precisamente, como el indicado anteriormente, algo que como vamos a ver que no es una buena opción de seguridad.

Figura 1: Un HASH MD5 en la password no sustituye a SSL

En este caso el usuario viaja en texto plano - aunque también se hasheaba en MD5 con una salt  - mientras que la contraseña es hasheada en MD5, después se concatenaba con un salt, para después volverse a hashear en MD5. A continuación se puede ver un sitio web que realiza el login de la forma indicada anteriormente. Podemos ver que el código fuente del sitio web cumple con el patrón md5(md5($pass).$salt), por lo que sabemos cómo se genera el hash enviado por la aplicación. ¿Esto sirve? Realmente no nos servirá de mucho, ya que con un simple sniffer y encontrándonos en medio de la comunicación tenemos los hashes y la salt, por lo que podemos realizar fuerza bruta o un ataque de diccionario. Además, MD5 no es un sistema que a día de hoy se pueda considerar robusto, así que aunque la password sea compleja acabará saliendo con algo más de tiempo. Simplemente ojeando el código Javascript del sitio web tenemos a nuestro alcance cuál es el procedimiento que utilizamos para hashear y después enviar la contraseña.

Figura 2: Código para hashear la password

El salt viaja en una conexión no segura por lo que podremos interceptarla en un ataque, por ejemplo, de MiTM. Por otro lado, podemos ver como el patrón para generar el hash del usuario es md5($user.$salt), por lo que éste es más sencillo, y además en el mismo paquete viaja el usuario en texto plano, por lo que es fácil comprobar que encaja.

Cómo atacar este sistema de cifrado

Realizando un ejercicio básico rápido iniciamos sesión con el usuario pepe y la contraseña ‘123456’, la cual es una de las más utilizadas por muchos usuarios en el mundo, y por tanto debe existir en cualquier diccionario para ataques de fuerza bruta. Configuramos Firefox para pasar por un proxy, que en este caso será nuestro ZAProxy con el fin de poder observar los datos que estamos enviando. En un escenario real, por ejemplo una auditoría, podríamos capturar esta información a través de Wireshark, y cualquier herramienta para hacer ataques en redes de datos como para realizar un esquema de ARP Spoofing sobre la víctima o cualquier otro de los ataques que hace Evil Foca.


Figura 3: Capturando los datos con ZAProxy

Una vez capturados los datos, podemos utilizar cualquier servicio online que genere MD5 con salt para verificar que teniendo la semilla es cuestión de tiempo. Un servicio que permita crackear un hash MD5 con semilla nos proporcionará diversas configuraciones. En la siguiente imagen podemos ver uno que nos ofrece distintas posibilidades típicas de aplicaciones web que podemos encontrarnos en Internet.

Figura 4: Cracking de hashes MD5 con distintas funciones de anidación

Como se puede ver se utilizan diferentes formas de hashing, aunque al final es posible realizar un ataque de fuerza bruta conociendo el salt y teniendo los hashes.

Autor: Pablo Gonzalez Pérez (@pablogonzalezpe)
Project Manager en Eleven Paths

3 comentarios:

  1. Muy buen artículo..!

    En este caso no hace falta ni siquiera romper el hash.

    Si el cliente envía un hash md5 a partir de los datos que ingresa el usuario, entonces una vez que hacemos MITM podemos utilizar directamente esos datos para autenticarnos, porque son los que el servidor espera recibir. La autenticación no la haríamos desde el formulario (porque éste sí necesita el usuario y la clave planas, sin md5) pero sí podríamos hacerla simulando el submit que hace el Javascript luego de hashear.

    Saludos!!

    ResponderEliminar
  2. @v45ch3: Me imagino que el servidor envía un salteo diferente en cada sesión.

    ---

    sha1(upper($username).':'.upper($pass)) 😱

    ResponderEliminar
  3. pensaba justo en lo que comentaba
    v45ch3
    De hecho me di cuenta al planear un minijuego que estoy desarrollando que mandarme el score de una manera similar era ridiculamente inseguro por eso mismo.

    ResponderEliminar