La idea de este post es sencilla pero interesante: tomemos una gran cantidad de contraseñas que se hayan filtrado de algún sitio web, almacenadas originalmente como el resultado de aplicar alguna función de hash a ellas, y veamos cuántas podemos romper en una hora. Adicionalmente, sería deseable que lo hiciéramos sin demasiados recursos y con técnicas no muy complicadas. Así, si logramos romper una buena cantidad de ellas, podemos llegar a una reflexión sobre las capacidades que tendrían los cibercriminales con equipos más potentes y técnicas más refinadas.
Para poder llevar a cabo estas pruebas como mínimo es necesario contar con:
- una lista de hashes a romper.
- una lista de palabras comunes utilizadas en contraseñas, a la que se conoce como diccionario.
- alguna aplicación que calcule la función de hash para las palabras de la segunda lista y compare el resultado contra los hashes de la primera lista.
A lo largo de los últimos años hemos observado ataques a grandes compañías en Internet, produciéndose importantes fugas de información. Es muy notorio el caso de Playstation Network, en el que no solo se filtró información de usuario y contraseña, sino también datos personales y bancarios. También recordamos el caso de Yahoo!, en el que se filtraron contraseñas que estaban almacenadas en texto plano en la base de datos. Sin embargo, las empresas son cada vez más conscientes de que no se debe almacenar las contraseñas sin antes aplicarles alguna transformación: en el caso de LinkedIn, las contraseñas filtradas tenían aplicada la función SHA1. Dado que la función no puede ser aplicada a la inversa para obtener las contraseñas a partir de los hashes, los cibercriminales se ven obligados a calcular la función para distintas palabras, y comparar contra los valores que se filtraron. Además, sería ideal que el hashing se aplique en varios niveles, que se utilicen "granos de sal" y otras técnicas más para dificultar la tarea de los atacantes.
Por lo tanto, para que este experimento sea válido será deseable utilizar contraseñas reales. Por ello, se partirá de un set inicial de 415321 hashes distintos, correspondientes a contraseñas de Battlefield Heroes que se filtraron en junio de 2011. En este caso, la función de hash aplicada antes de almacenar las contraseñas era MD5, lo cual simplificará mucho las pruebas, al ser un algoritmo de cálculo rápido. Como diccionario se utilizará la lista de RockYou, que contiene más de 14 millones de contraseñas reales. Curiosamente, esta lista también surgió de un caso de fuga de información, por lo que hoy en día forma parte del arsenal de casi cualquier cracker. Por último, la aplicación a utilizar será hashcat, cuyo funcionamiento hemos analizado antes en este blog.
Para empezar, se utilizará la versión de hashcat de Windows con interfaz gráfica: es probable que la mayoría de nosotros tengamos a mano una computadora con Windows y que no deseemos ingresar comandos largos ni aprender la sintaxis de hashcat, con lo cual ésta es la mejor opción. En la siguiente imagen se observa una captura de pantalla de esta aplicación:
Primero se especifica el archivo con los hashes a romper; en este caso la lista de Battlefield Heroes. Luego el modo de ataque; inicialmente se hará un ataque directo: aplicar MD5 a las palabras del diccionario y comparar con la lista de hashes para encontrar coincidencias. Por último se elige el archivo donde se almacenarán las contraseñas recuperadas, es decir, aquellas que "coincidieron". Antes de presionar el botón, cabe aclarar que la ejecución se llevará a cabo en una laptop con un procesador Core i5 de Intel de media gama, simplemente porque es la computadora que tenía a mano. Si bien el procedimiento puede acelerarse con la versión de hashcat que soporta procesamiento por GPU, en este experimento sólo utilizaremos la CPU. Quizás no se obtengan los mejores resultados, pero justamente esa es la idea: utilizar hardware que cualquiera puede tener en casa.
Cuando se presiona el botón comienza el procesamiento. Entonces, ¿qué realiza nuestro procesador? Calcular la función MD5 para cada una de las 14 millones de palabras en el diccionario, y comparar contra cada uno de los 400 mil hashes en la lista. Luego de sólo 2 minutos de ejecución se completa la operación, arrojando los siguientes resultados:
Se han recuperado casi 120 mil contraseñas en 2 minutos. Aquí vemos la utilidad de este diccionario y por qué se ha hecho tan popular. Para el siguiente paso utilizaremos el mismo diccionario, pero además aplicaremos reglas a cada una de las palabras antes de calcular la función. Podríamos, por ejemplo, sacar algunas letras y remplazarlas por otras, o ignorar palabras muy largas o muy cortas, entre otras operaciones. Si bien es posible crear nuestras propias reglas, en este caso se utilizarán reglas que vienen incluidas con hashcat, dado que es lo más sencillo y no tenemos mucho tiempo. Así, se agregará el archivo de reglas best64, el cual condensa aquellas reglas que se creen que son las más usuales en el armado de contraseñas. Se invertirán las palabras, se pasará de mayúscula a minúscula y viceversa y se concatenarán números muy utilizados al final de cada palabra, por mencionar sólo algunas de las reglas. Como resultado de este proceso se han obtenido 71892 contraseñas más en 2 minutos y medio de ejecución:
Como siguiente paso, se llevaron a cabo las mismas operaciones con otros diccionarios más pequeños, buscando encontrar palabras que no estuvieran en el diccionario inicial. Para ello se utilizaron, entre otros, un diccionario con palabras de Wiktionary en inglés, y un set de palabras del idioma español. Primero se hizo la comparación directa, obteniendo 2298 contraseñas más, y luego se utilizaron las reglas de best64, recuperando 3113 contraseñas adicionales.
Además de best64, hashcat incluye otros sets de reglas sumamente efectivos. Para los pasos sucesivos se utilizó el set "d3ad0ne", el cual contiene muchas más reglas que best64, pero también demora un tiempo considerable en su ejecución. Así, dado que d3ad0ne para el diccionario de RockYou demoraría horas, se decidió empezar por otro diccionario más pequeño, el que se filtró de phpBB. Si bien este diccionario sólo tiene 180 mil palabras, la ejecución durante 5 minutos con estas reglas produjo 23495 contraseñas más. Luego, al realizar la ejecución con d3ad0ne y el diccionario con palabras en español, el tiempo proyectado era de 12 minutos. Sin embargo, luego de los 5 minutos de ejecución la cantidad de contraseñas recuperadas iba creciendo a un ritmo cada vez más lento, por lo que decidí terminar luego de 6 minutos y 1066 contraseñas.
Luego se realizó el mismo proceso con el set d3ad0ne y varios diccionarios pequeños, sumando 10 minutos en total entre todos ellos y 5295 contraseñas más. Antes de desechar estas reglas, decidí ejecutar el proceso para el diccionario de RockYou, terminándolo en tanto no notara progresos importantes. Si bien lo dejé para el final, este diccionario nuevamente no me defraudó: como se observa en la imagen, el proceso iba a tardarse más de 3 horas, pero lo corté luego de 14 minutos y un buen número de contraseñas: 10205.
Ahora, dado que sólo quedan unos minutos y nos propusimos terminar en una hora, vamos a aprovechar una propiedad bastante interesante de las contraseñas. Si bien los usuarios de un sitio web no se conocen entre sí, y son totalmente independientes, las contraseñas para un mismo sitio o servicio tienden a ser similares. Por lo tanto, si bien es lógico pensar que algún porcentaje de los usuarios de Battlefield Heroes tendrán contraseñas relacionadas con ese juego, lo que estamos diciendo es que tomando algunas contraseñas y realizando pequeñas modificaciones podemos obtener otras contraseñas. Luego, al tomar todas las contraseñas recuperadas hasta el momento como un diccionario y utilizar reglas, deberíamos obtener buenos resultados. Con best64 se recuperaron 724 contraseñas en 2 segundos, y con d3ad0ne 9714 en 7 minutos y medio.
En resumen, se ha logrado romper 251346 contraseñas en una hora utilizando sólo métodos de comparación con diccionarios. A partir de este momento podrían utilizarse métodos de fuerza bruta o híbridos (fuerza bruta con diccionarios), pero no los utilizaremos en esta ocasión por cuestión de tiempo y recursos. En la siguiente imagen se muestran algunas de las contraseñas recuperadas. Algunas de ellas son muy malas (como '123456789' o 'password'), otras son fácilmente atacables por diccionario (como 'killerbee321') y la última parece ser fuerte, pero al ser tan corta ha podido ser rota también:
En base a las contraseñas obtenidas puede hacerse un análisis para determinar cómo debe encararse el proceso de fuerza bruta o ataques híbridos. Nuevamente, de las contraseñas que ya se conocen se puede saber mucho acerca de las que todavía faltan obtener. Gran parte de las contraseñas tienen de 6 a 8 caracteres, y muchas de ellas sólo tienen caracteres en minúscula y dígitos (48%) o sólo caracteres en minúscula (30%). En la siguiente gráfica se observa la longitud de las contraseñas obtenidas y el porcentaje asociado:
Para concluir este simple experimento queremos notar algunas cosas. Primero, que se recuperó el 29% de las contraseñas en sólo 2 minutos; y el 60% de ellas en 60 minutos. Por lo tanto, el proceso no es lineal y a medida que se recuperan contraseñas, más difícil es recuperar las restantes. Luego, que se haya roto el 60% de los hashes en una hora no implica que se vaya a romper el 100% en dos horas. En segundo lugar, desde que se filtraron los hashes se ha roto el 98% de ellos, lo cual representa un porcentaje de éxito muy grande. Por lo tanto, parece ser que los resultados hablan por sí solos: si con herramientas básicas, con poco tiempo y con pocos recursos y técnicas empleadas hemos logrado un 60% en 60 minutos, ¿qué queda para los que pueden hacer esto en mejores condiciones? Probablemente hablaríamos de un 75 a 80% en una hora. Por eso, ahora la responsabilidad está en los usuarios: utilicen contraseñas fuertes y gestiónenlas.
Matías Porolli
Especialista de Awareness & Research