El objetivo de este post es familiarizarse con la herramienta más potente del mundo actualmente para comprobar la calidad de las contraseñas, hashcat, un cracker extremadamente rápido y versátil que permite verificar y romper una gran cantidad de hashes diferentes, y por lo tanto verificar la robustez de una clave.
Como se puede apreciar en el siguiente artículo, hashcat es capaz de romper cualquier contraseña de 8 caracteres cuyo hash sea NTLM (Windows) en menos de 2h y media gracias al empleo de núcleos CUDA:
https://informationsecuritybuzz.com/hashcat-can-now-crack-an-eight-character/
Incluso existen proyectos de código abierto para desplegar servidores de creackeo (con hashcat) distribuidos como lo es “Hashtopolis” y así orquestar las tareas de verificación de claves:
https://github.com/hashtopolis/server
Para la realización de esta práctica se requiere instalar hashcat en un sistema operativo anfitrión par que pueda hacer uso de los núcleos CUDA de la GPU, independientemente de que sea un sistema Windows o Linux.
En mi caso, lo he instalado en Windows 10 siguiendo las instrucciones del sitio web oficial de hashcat:
Uno de los principales motivos por los que haré uso de Windows es, simplemente, que Hashcat es mucho más sencillo y rápido de configurar. Sin embargo, aunque en sistemas GNU/Linux sea más complicado y engorroso, si se logra configurarlo con éxito, la velocidad de cracking aumenta considerablemente.
Aprovecho para comentar que es curioso que hashcat se promocione (porque no se vende) como una herramienta avanzada de recuperación de contraseñas.
Cabe destacar que mi equipo cuenta con una tarjeta gráfica dedicada NVIDIA RTX 3070 con 8GB de VRAM.
Antes de comenzar con los ejercicios propuestos, se utilizará un archivo con hashes extraídos del fichero “/etc/shadow” (de un sistema Unix cualquiera) a través de herramientas como Mimikatz. En este fichero hay 9 usuarios con sus respectivos hashes.
Los usuarios “user1.1”, “user1.2” y “user1.3” son para el ejercicio 1, los “user2.1”, “user2.2” y “user2.3” son para el ejercicio 2 y “user3.1”, “user3.2” y “user3.3” son para el ejercicio 3.
En este ejercicio atacaremos a los hashes de los usuarios “user1.1”, “user1.2” y “user1.3” sabiendo como única pista que sus contraseñas son palabras que se pueden hallar en cualquier diccionario (como por ejemplo, Rockyou.txt):
También se ha recomendando pasar el parámetro “--potfile-disable” para que hashcat no guarde los hashes crackeados/resueltos en un base de datos, comportamiento que ocurre por defecto y en el caso de este ejercicio nos roba un tiempo muy valioso.
Lo primero que vamos a hacer es generar un fichero .txt que contenga exclusivamente los hashes UNIX, lo cual se puede hacer a mano de forma gráfica o mediante el siguiente comando de powershell:
En un sistema GNU/Linux (como Kali), se podría hacer de forma todavía más simple mediante el comando <cut>:
Por ejemplo, <cut -d':' -f2 shadow.txt > hashes.txt>.
Una vez ya tenemos un fichero que contiene solamente los hashes de los usuarios, podemos pasar a lanzar el ataque.
Cabe mencionar un pequeño tip adicional: al grepear los hashes con sus respectivos usuarios y usar --username en Hashcat, se puede verificar fácilmente qué contraseña corresponde a cada usuario sin interferir con el ataque.
Lo primero que haremos será realizar un pequeño benchmark para verificar la correcta funcionalidad de hashcat mediante el siguiente comando:
El benchmark comienza a ejecutar pruebas para ver cuántas iteraciones por segundo se podrían alcanzar, como se ve en la captura de pantalla anterior el hash cuyo modo corresponde al “1800” (hash sha512crypt - $6 UNIX) alcanza unas 191.2 kH iteraciones por segundo con mi GPU dedicada de NVIDIA, es decir, cerca de 200.000 iteraciones / hashes que verifica cada segundo, lo cual está bastante bien.
Ahora, siguiendo la ayuda que proporciona hashcat mediante el parámetro “-h”, lanzaremos el ataque de diccionario:
El comando final a ejecutar para lanzar el ataque sería el siguiente:
Veamos el resultado, cabe destacar que en un escenario real, es muy posible que las claves de los usuarios del sistema UNIX no se encuentren en el diccionario.
Cabe destacar que la codificación del fichero de hashes .txt debe ser “UTF-8 sin BOM”, de lo contrario puede que hashcat no detecte los hashes, esto se puede modificar por ejemplo mediante herramientas gráficas cono notepad++ en Windows:
Como podemos apreciar en las capturas anteriores, el ataque ha tenido éxito en apenas 1 segundo (que es lo que le ha costado a hashcat ejecutarse) y se han logrado crackear las 3 contraseñas, que son las siguientes:
Esto podemos verificarlo y guardarlo si además al comando con el que hemos lanzado el ataque le pasamos un parámetro extra para generar un fichero .txt con las claves obtenidas, concretamente el “--outfile-format X”, donde “X” es uno de los siguientes números:
Se pueden combinar como deseemos,el comando completo es:
1.\hashcat.exe -a 0 -d 1 -m 1800 --potfile-disable --outfile ejer1_resuelto.txt --outfile-format 1,2,3,4,5 .\hashes_ejer1_limpios.txt .\500_passwords.txt
En este ejercicio ejecutaremos hashcat para lanzar un ataque y comprobar la robustez de las contraseñas de los usuarios “user2.1”, “user2.2” y “user.2.3”.
Repetiremos el proceso de generación de un fichero .txt que contenga los hashes limpios para haschat como se ha realizado en el apartado anterior.
Como pista que se nos da, su claves poseen 6 caractéres, los 3 primeros 3 letras minúsculas y los 3 últimos corresponden a 3 dígitos (números).
Para lanzar el ataque, muchos de los parámetros del ejercicio 1 se utilizarán en este, principalmente modificaremos el método / modo del ataque:
Si no le pasamos ninguna máscara, se utilizarán aquellas que están predefinidas por hashcat:
A continuación, se detallan las máscaras que podemos utilizar en hashcat:
Como la pista que nos han proporcionado parece apuntar a que las claves son de 6 caracteres, probaremos la siguiente máscara para lanzar el ataque:
?l?l?l?d?d?d --> 3 letras minúsculas y luego 3 dígitos, todas las combinaciones posibles.
El comando sería:
1.\hashcat.exe -a 3 -d 1 -m 1800 --potfile-disable --outfile ejer2_resuelto.txt --outfile-format 1,2 .\hashes_ejer2_limpios.txt ?l?l?l?d?d?d
Veamos el estado:
Finalmente:
Como podemos apreciar en la captura anterior, en apenas 5 minutos he crackeado las claves:
Cabe destacar que si por ejemplo no supiéramos la longitud exacta de la clave, pero sabemos que solamente posee 1 tipo de carácter, pongamos el ejemplo de un PIN compuesto por números, podríamos hacer uso del parámetro “-i” que referencia al modo incremental. Por ejemplo, lo podríamos utilizar si la clave fuera un PIN númerico de entre 4 y 8 dígitos.
Como nota adicional, los routers y puntos de acceso TP-LINK configuran por defecto sus redes Wi-Fi WPA2-PSK con claves que son básicamente un PIN de 8 dígitos, por lo que en caso de realizar una auditoría de la red inalámbrica mediante suites de herramientas como aircrack-ng, y así obtener el handshake, podríamos crackearlo mediante hashcat en cuestión de minutos.
En este ejercicio ejecutaremos hashcat para lanzar un ataque y comprobar la robustez de las contraseñas de los usuarios “user3.1”, “user3.2” y “user.3.3”.
Repetiremos el proceso de generación de un fichero .txt que contenga los hashes limpios para haschat como se ha realizado en el apartado anterior.
Como pista que se nos da, solamente sabemos que las claves contienen una palabra del diccionario que hemos empleado en el ejercicio 1 y posteriormente un año comprendido entre el 2000 y el 2020.
Para lanzar el ataque, muchos de los parámetros del ejercicio 1 y 2 se utilizarán en este, principalmente modificaremos el método / modo del ataque puesto que ahora ejecutaremos un ataque híbrido que empleará tanto las máscaras de hashcat como un diccionario:
Acerca de la máscara a utilizar, lamentablemente en hashcat no se pueden crear rangos como tal, por lo que tenemos dos opciones para la máscara del año entre el 2000 y el 2020:
20?d?d --> del 2000 al 2099 (Muchas combinaciones innecesarias)
O
Lanzar 3 comandos de hashcat distintos con rangos más ajustados:
200?d --> del 2000 al 2009
201?d --> del 2010 al 2019
202?d --> del 2020 al 2029
Por comodidad, utilizará la máscara que comprende del año 2000 al año 2099, a ver cuánto tiempo tardaría con mi GPU dedicada.
El comando sería el siguiente:
1.\hashcat.exe -a 6 -d 1 -m 1800 --potfile-disable --outfile ejer3_resuelto.txt --outfile-format 1,2 .\hashes_ejer3_limpios.txt .\500_passwords.txt 20?d?d
Finalmente:
Como podemos apreciar en la captura anterior, hashcat ha tardado 2 minutos y 15 segundos.
Puesto que dispongo de una GPU potente, puedo permitirme el lujo de no afinar tanto, sin embargo lo ideal siempre será utilizar máscaras que brinden la máxima eficiencia para reducir el tiempo de crackeo, aunque haya que dividir el ataque en varios comandos de hashcat.
Veamos los resultados del ataque:
Como podemos observar, hemos completado todos los ejercicios con éxito, además de observar lo fácil que es romper una clave débil con las herramientas que disponemos a día de hoy, por lo que una buena generación y gestión de claves es fundamental para garantizar una buena seguridad a nivel de credenciales robustas. Esta tarea podemos llevarla a cabo gracias a gestores de contraseñas como Bitwarden o KeePassXC. En relación a Bitwarden, si no nos fiamos de sus servidores aunque según la doc explican bastante bien como almacenan los hashes de nuestras contraseñas y que realizan bastantes auditorías frecuentemente, podríamos instalar una versión opensource del servidor de Bitwarden para que nosotros gestionemos dónde se guardan nuestras claves: