Cracking de contraseñas con hashcat

En esta entrada, he querido hacer una recopilación de los distintos métodos de ataque para la obtención de contraseñas mediante la herramienta Hashcat, posiblemente la herramienta más extendida y eficaz para este propósito, al alcance de cualquier persona interesada en el tema.

Para ello he decidido utilizar la versión 3.00 de la misma, ya que a partir de esta versión se deja de lado la separación entre ataques basados en la potencia de la CPU(antiguo Hashcat) y los ataques basados en la potencia de las tarjetas gráficas (HaschatOCL), para unir en una sola herramienta ambas opciones, aunque la mayor parte de los ataques que se explicarán en este artículo son válidos en versiones anteriores de esta herramienta.

Una de las tareas más importantes a la hora de crackear contraseñas cuando no disponemos de tiempo infinito (que suele ser bastante a menudo), es la planificación del propio ataque. Para ello, deberemos medir el tiempo que tenemos para el mismo, y en función de éste, limitar nuestras opciones de crackeo a aquellas tipologías de contraseña que creamos más probables de obtener en el tiempo que disponemos. Ésta no es una tarea sencilla, ya que la tipología de las contraseñas utilizadas puede depender de muchos factores entre los que se encuentra, por ejemplo, el país y el lenguaje de los usuarios de esas contraseñas o la edad media de los mismos, por lo que cuanta más información de contexto tengamos más podremos afinar en nuestra planificación.

Aun así, todos sabemos que la raza humana, con toda la diversidad de civilizaciones, etnias, ideologías, niveles socioculturales y económicos que la conforman, converge en un único pensamiento cuando de forma inesperada, recibe estas solemnes palabras: “Inserta tu nueva contraseña”: “Pues pongo mi nombre”

Afortunadamente, existieroncd /pwd personas antes que nosotros que se dieron cuenta de este hecho y pusieron límites a este pensamiento, haciendo obligatorio que la respuesta a esa pregunta contuviera, por ejemplo, mayúsculas, minúsculas y algún número. Pero una vez más, gran parte de la humanidad se unió telepáticamente para dar una repuesta única: “Pues mi nombre en mayúscula y mi año de nacimiento”.

Evidentemente he exagerado un poco en esa respuesta única, todas las personas no son iguales, por lo que existen distintas variantes de esa respuesta en las que se puede cambiar el nombre de la persona por el nombre de la mascota o el nombre del pueblo natal y la fecha de nacimiento por la edad en años, con la ventaja añadida de que se puede cambiar cada año de contraseña simplemente sumándole un año a la del año anterior. Todas estas variantes hacen del crackeo de contraseñas un ejercicio bastante entretenido.

A modo de ejemplo para este post, elegiremos nos centraremos en el objetivo de obtener las contraseñas de un máximo de 12 caracteres, que empiecen por un nombre seguido de la fecha de nacimiento, e intentaremos optimizar esta búsqueda mediante las distintas opciones que nos ofrece hashcat.

En primer lugar, partiremos de la base que ya disponemos de la herramienta hashcat en nuestro equipo y de que tenemos un archivo hashdump.txt con hashes de contraseñas obtenidos en una auditoria a equipos Windows mediante la herramienta hashdump, el cual tiene el siguiente formato:

user1:7362:aad3b435b51404eeaad3b435b51404ee:b562d5031359813a06914d562d421acd:::
user2:7787:aad3b435b51404eeaad3b435b51404ee:3b7a5bb9f8a12f74dadb7adf740cf7c1:::
user3:7788:aad3b435b51404eeaad3b435b51404ee:2501dd5aa075d4854559a5ee023df798:::
user4:7789:aad3b435b51404eeaad3b435b51404ee:11cdb1cb2b21aba701d1113fcf6e3c4f:::
user5:7790:aad3b435b51404eeaad3b435b51404ee:722ab3c822cb6a49bf89830bb5ffaea9:::
user6:7800:aad3b435b51404eeaad3b435b51404ee:79aff34e34c1fa16fffc7c6765e23636:::
user7:7801:aad3b435b51404eeaad3b435b51404ee:73366d77424b259794cac80f4e3fc8c9:::
user8:7803:aad3b435b51404eeaad3b435b51404ee:e2ad4eff06322cf9240ab93288fda61c:::

Este formato contiene, para cada línea, los siguientes campos separados por ‘:’

(Usuario):(SID):(hash LM):(hashNTLM):::

Como podemos observar, el tercer campo (hash en formato LM) es siempre el mismo para todas las entradas (aad3b435b51404eeaad3b435b51404ee). Este hash corresponde con el hash LM de la cadena vacía, e indica que el sistema de donde hemos obtenido la tiene deshabilitado los hashes LM (deshabilitado por defecto a partir del Windows Vista), por lo que nos centraremos en el cuarto campo (hash NTLM).

Lo primero que haremos crear un archivo ntlm.hp que contenga únicamente ese campo, mediante cualquier herramienta que nos lo permita, por ejemplo AWK:

awk –F’:’ ‘{print $4 >> ntlm.hp}’ hashdump.txt

Ahora necesitamos indicarle a hashcat el tipo de hash que le estamos proporcionando, y lo haremos utilizando el parámetro –m (hash mode).

Observando el apartado [ Hash modes ] con el comando ./hashcat64.bin -h podemos obtener este valor (1000):

Con todo esto, lo siguiente será elegir entre los distintos tipos de ataques que nos proporciona Hashcat, los cuales los podemos ver en el apartado [ Attack Modes ] de la misma ayuda.

0 – Straight

Este ataque es el que conocemos como ataque por diccionario. Haschat comprobara si la contraseña corresponde con alguna de las palabras del diccionario que le pasemos como argumento.

1 – Combination

En este caso, hashcat recibirá dos diccionarios como argumentos, y comprobará si la contraseña corresponde con la combinación de cada uno de los términos del primer diccionario con cada uno de los términos del segundo.

3 – Brute-force

Al contrario de los casos anteriores, en este caso el propio hashcat será el encargado de generar las contraseñas que comprobara contra los hashes. Para esto, se basará en las llamadas máscaras, mediante las cuales podremos indicarle que tipo de contraseñas queremos que genere.

4 – Hybrid

Hashcat nos permite combinar la potencia de los ataques por diccionario y los ataques por fuerza bruta (mask atacks). En los ataques híbridos, podremos generar parte de una contraseña con los términos de un diccionario y completarla mediante máscaras.

Como hemos adelantado anteriormente, a continuación intentaremos cumplir nuestro objetivo de obtener todas aquellas contraseñas que contengan un nombre seguido de una fecha de nacimiento mediante los tipos de ataque mostrados anteriormente.

Brute-force (Ataque con máscaras)

Para ejecutar esta modalidad de ataque sobre nuestro archivo de hashes NTLM, únicamente necesitaremos decirle a hashcat que el tipo de hashes que contiene el archivo es NTLM (-m 1000) y que queremos ejecutar un ataque por fuerza bruta (-a 3).v

hashcat64.bin –m 1000 –a 3 ntlm.hp

Si ejecutamos este comando, hashcat generará y comprobará contraseñas a partir de una serie de máscaras predefinidas por defecto, pero para el objetivo de este artículo, crearemos nuestras propias máscaras.

¿Pero que es una máscara? Una máscara es un conjunto de reglas que indican como están formadas las contraseñas que queremos generar. Más concretamente, una máscara especificará, para cada posición de la contraseña, el conjunto de caracteres que puede tener.

Cada posición de nuestra máscara puede contener un carácter fijo o un charset, que no es más que un conjunto caracteres.

Al contrario de los caracteres fijos, los charsets irán precedidos del signo de interrogación.

En la propia ayuda de hashcat podemos observar los charsets predefinidos de hashcat:

Como se puede observar, todos los charsets son una serie de caracteres definidos, excepto el charset ?a, que está formado por la combinación de los charsets ?l,?u,?d y ?s.

La razón de esto es que hashcat permite definir un charset como la combinación de otros charsets, por ejemplo, si quisiéramos definir un charset que contuviera tanto mayúsculas como minúsculas podríamos definirlo de la siguiente manera: ?l?u

Ejemplos de ataques utilizando máscaras:

hashcat64.bin –m 1000 –a 3 ntlm.hp pass1234

Comprobaría únicamente la contraseña (pass1234), mientras que el comando:

hashcat64.bin –m 1000 –a 3 ntlm.hp pass?d?d?d?d

Comprobaría todo el espectro de contraseñas que empezaran por “pass” y cuyos cuatro siguientes caracteres fueran dígitos decimales (pass0000-pass9999)

Mediante la máscara ?a?a?a?a?a?a?a?a?a?a?a?a, podemos simular un típico ataque por fuerza bruta para comprobar todas las contraseñas de 12 caracteres de cualquier combinación de dígitos decimales, signos, mayúsculas y minúsculas.

Además, para no tener que crear una máscara para cada longitud de contraseña que queramos probar, hashcat nos proporciona el argumento –i (–increment), con el que hashcat irá probando iterativamente las n primeras posiciones de la máscara para cada iteración hasta el máximo de caracteres que hayamos especificado con el argumento –increment-max o el tamaño de la máscara en caso de que no se lo hayamos especificado.

Por ejemplo para el comando:

./hashcat64.bin –m 1000 –a 3 ntlm.ph ?a?a?a?a?a –i –increment—min 2 increment—max 4

Se probarán secuencialmente las máscaras:

?a?a

?a?a?a

?a?a?a?a

Como podemos observar en la línea Progres y Time.estimated de la imagen, al ejecutar el ataque mediante la máscara ?a?a?a?a?a?a?a?a?a?a?a?a, se generarán y se comprobarán un total de 180602555536776954753 combinaciones, que en nuestra máquina, que dispone de 2 potentes tarjetas gráficas, tardaría más de 10 años en completarse.

Con el fin de reducir las combinaciones posibles para nuestro objetivo, podríamos utilizar la máscara ¿u?l?l?l?l?l?l?l?ld?d?d?d que comprendería todo el espectro de contraseñas desde Aaaaaaaa0000 hasta Zzzzzzzz9999.

Esto incluiría prácticamente todos los nombres posibles de hasta 8 letras seguidos de todas las fechas de nacimiento desde el año 0 hasta el 9999 D.C.

Aunque hemos reducido considerablemente el tiempo necesario para probar todas las posibles combinaciones de nuestro objetivo de más de 10 años a menos de 2 días, todavía estamos probando muchas contraseñas que no se ajustan a nuestro objetivo, como por ejemplo todas aquellas que contengan una fecha de nacimiento anterior a 1900 o posterior a 2017, por lo que todavía podemos intentar reducir este tiempo creando una máscara que descarte las mismas, y para ello, será necesario definir nuestros propios charsets.

Hashcat permite utilizar para cada ataque 4 charsets (custom-charsets) personalizables por el usuario, mediante los argumentos -1, -2, -3 y -4.

En este caso, necesitaremos crear 2 máscaras, una para aquellas contraseñas que contengan la fecha de nacimiento desde 1900 hasta 1999:

./hashcat64.bin -m 1000 -a 3 ntlm.hp ?u?l?l?l?l?l?l?l19?d?d

Y otra para aquellas del 2000 al 2017.

./hashcat64.bin -m 1000 -a 3 ntlm.hp -1 01 -2 012345678 ?u?l?l?l?l?l?l?l20?1?2

Para esta última, hemos definidos 2 charsets propios:

-1 01, que utilizaremos para decirle a la máscara que el carácter que representa las decenas de la fecha de nacimiento solo podrá contener el valor 0 o 1, y así evitar que genere aquellas fechas desde 2020.

-2 012345678, que utilizaremos para evitar que genere la contraseña 2019.

EDIT: También elimina la 2009

Con esto, habremos reducido el tiempo de cerca de 2 días a menos de 30 minutos.

Hay que tener en cuenta que para nuestro objetivo, no podemos utilizar la opción –incremental, ya que esta opción no cumpliría nuestros requisitos al ir eliminando las últimas posiciones de la máscara, por lo que tendremos que crear una máscara distinta para cada longitud de contraseña de la siguiente manera:

¿u?l?l?l?l?l?l?l?ld?d?d?d

¿u?l?l?l?l?l?l?ld?d?d?d

¿u?l?l?l?l?l?ld?d?d?d

….

¿u?l?d?d?d?d

Para complicar algo más la cosa, algunos administradores, han tenido la valentía enfrentarse a la furia de los usuarios y les han obligado a crear contraseñas que contengan al menos, un signo de puntuación.

Para contemplar esta opción, podríamos añadir a nuestra máscara la opción de que se los nombres también contuvieran signos de puntuación.

Para ello añadiremos los customs-charsets:

-3 ?u?s : Donde antes habían mayúsculas ahora también pueden haber símbolos
-4 ?l?s : Donde antes habían minúsculas ahora también pueden haber símbolos

Como podemos observar, al añadir estas opciones volveremos a aumentar el tiempo estimado en 2 días, ¿podríamos optimizar esto un poquito más?

Una de las cosas a tener en cuenta con este ataque, es que obtendríamos aquellas contraseñas como Paquito.2010, pero también cosas como ##_*#.-##2010.

Aunque en algunos contextos puede valer la pena comprobar este tipo de contraseñas, Según nuestra teoría del pensamiento universal, la mayoría de gente intentará realizar el mínimo esfuerzo para cumplir con las políticas de contraseña, por lo que optarán con poner un solo símbolo de puntuación.

Con esta premisa, crearemos una máscara para cada posición en la que pueda estar el signo de puntuación, evitando así la generación de contraseñas en las que haya más de un signo de puntuación.

Con una media de 5 minutos y 30 segundos para cada máscara con un signo de puntuación, necesitaremos cerca de 60 minutos para comprobar todas las posibles posiciones del signo de puntuación.

Como hemos observado, para optimizar nuestra búsqueda, ha sido necesario crear distintas máscaras, lo que genera el inconveniente de tener que estar pendientes de que acabe un ataque con una máscara para ejecutar la otra.

Para evitar esta situación, hashcat permite pasarle como argumento un archivo de máscaras (una por línea), que ejecutara secuencialmente, para ello dispone del directorio masks, donde podemos encontrar ejemplos de máscaras. Además, esto nos permitirá tener almacenadas las diferentes estrategias de ataque que vayamos creando para utilizarlas cuando más nos convenga. En nuestro caso, el archivo con las máscaras tendría esta forma.

Como podemos observar en las últimas máscaras de la imagen, cuando especificamos nuestros propios charsets para cada máscara en un fichero, no lo haremos de la misma manera que en la línea de comandos. Sino que separaremos cada uno de los custom-charsets por comas.

Por ejemplo, donde antes teníamos los ataques:


./hashcat64.bin –m 1000 –a 3 -1 ABC -2 aeiou ?1?1?1?1?2?2?2?2
./hashcat64.bin –m 1000 –a 3 -1 ?l?u ?a?a?a?a?1?1?1?1

Ahora tendremos un fichero ejemplo.hcmask que contendrá las líneas:

ABC,aeiou,?1?1?1?1?2?2?2?2
?l?u,?a?a?a?a?1?1?1?1

Y ejecutaremos el ataque con el siguiente comando.

./hashcat64.bin –m 1000 –a 3 ejemplo.hcmask

Los charsets que definamos, también puedes que pueden ser almacenados en ficheros .hcchr para poder utilizarlos posteriormente. Encontraremos ejemplos de estos ficheros en el directorio charsets.

Straight (Ataque por diccionario)

Aunque hemos conseguido optimizar bastante nuestra búsqueda mediante ataques basados en máscaras, las probabilidades de que exista alguna persona que se llame Aaaaaaaaa o Zxcfdcvilio son bastante bajas, así que todavía tenemos opciones de optimizar nuestro ataque.

Cuando tenemos una lista de palabras que puedan ser candidatas a formar parte de las contraseñas que estamos buscando, existe la opción de realizar un ataque por diccionario. Para nuestro ejercicio, por ejemplo, podemos utilizar los datos que nos proporciona el instituto nacional de estadística en su página web www.ine.es/daco/daco42/nombyapel/nombyapel.htm, donde tenemos un listado con todos los nombres femeninos y masculinos junto con datos estadísticos, lo que nos permitirá además, crear un diccionario ordenado con los nombres de mayor a menor frecuencia, aumentando así la probabilidad de encontrar más contraseñas en un tiempo menor.

Para ejecutar este ataque únicamente necesitaremos indicarle el tipo de hash seguido del archivo de hashes y el archivo que contenga el diccionario, que en este caso será un archivo que contendrá los 9098 nombres más comunes de España.

./hashcat64.bin -m 1000 -a 0 ntlm.hp nombres.dict

Como podemos observar en la hora de inicio y fin del ataque, la finalización del mismo es casi instantánea.

Pero con este ataque, no estamos cumpliendo con el requisito de que las contraseñas que finalicen con una fecha de nacimiento. Para cumplir con este requisito, tendríamos la opción de modificar el diccionario añadiendo a cada nombre incluido en el todas las fechas posibles, pero hashcat nos facilita esta tarea mediante los ataques híbridos.

Ataques híbridos ( diccionario + máscara)

Hashcat dispone de dos variantes de ataques híbridos, la opción -6 (dict + mask), en la que generará contraseñas añadiendo la máscara al final de cada término de diccionario, y la opción -7, en los que generará contraseñas añadiendo la máscara al inicio de cada termino.

Para el objetivo que nos traemos entre manos, bastaría ejecutar un ataque hibrido -6 (dict+mask) con el fin de añadir todas las posibles fechas a cada nombre del diccionario. Teniendo en cuenta que la ejecución del ataque por diccionario ha sido instantánea, nos permitiremos el lujo de utilizar como mascara todas las combinaciones de 4 dígitos (d?d?d?d).

./haschat64.bin -m 1000 -a 6 ntlm.hp nombres.dict ?d?d?d?d


Este ataque también finaliza instantáneamente.

Aunque los tiempos obtenidos mediante el ataque por diccionario y los ataques híbridos han sido con diferencia los más bajos de todas las pruebas, estos ataques ofrecen poca flexibilidad para generar contraseñas con patrones más complejos, como por ejemplo, para añadir que la primera letra del nombre sea en mayúscula (habría que añadir todos los nuevos nombres con la inicial en mayúscula al diccionario), o considerar la opción de que haya un signo de puntuación presente en la contraseña.

Para ello, hashcat nos ofrece lo que llama ataques basados en reglas. Pero esto lo veremos en la segunda parte de este post.