Crackear la passphrase de una clave privada SSH con hashcat y John the Ripper
Extrae el hash de un id_rsa o id_ed25519 cifrado con ssh2john, elige el modo hashcat correcto para claves PEM clásicas y descubre cuándo solo John the Ripper puede atacar una clave OpenSSH moderna.
Una clave privada SSH cifrada no es más que otro secreto protegido por contraseña, y como cualquier otro se reduce a la misma pregunta: extraer un hash, elegir la herramienta y el modo correctos, lanzar un diccionario. La particularidad de las claves SSH es que dos formatos muy distintos se esconden tras la misma cabecera -----BEGIN ... PRIVATE KEY-----, y hoy en día solo uno de ellos puede tocarlo hashcat.
Dos formatos de clave, dos problemas distintos
Las claves más antiguas —cualquiera generada con ssh-keygen -m PEM, o producida por herramientas que aún usan el formato tradicional por defecto— son archivos PEM al estilo OpenSSL. La passphrase deriva una clave simétrica mediante un KDF simple basado en MD5, que luego descifra la clave RSA/DSA/EC incrustada con DES, 3DES o AES-CBC según lo que indique la cabecera.
Desde OpenSSH 7.8 (2018), ssh-keygen escribe por defecto el nuevo contenedor openssh-key-v1 para todo tipo de clave, incluido el ya habitual id_ed25519. El único KDF que admite ese formato es bcrypt-pbkdf, deliberadamente más lento y más exigente en memoria que el antiguo esquema MD5 —buena noticia si es tu clave, mala si eres el atacante, y la razón por la que muchos «lancé hashcat contra mi clave y dio error» resultan ser una incompatibilidad de formato y no un problema de cracking.
Extraer el hash con ssh2john
Ambos formatos pasan por la misma herramienta. ssh2john.py viene incluido en la distribución jumbo de John the Ripper (en Kali, normalmente en /usr/share/john/ssh2john.py o /opt/john/ssh2john.py) e inspecciona la cabecera de la clave para decidir cómo interpretarla:
python3 /usr/share/john/ssh2john.py id_rsa > hash.txt
El resultado es una sola línea con el prefijo $sshng$, seguida de un identificador de cifrado, los parámetros del KDF y el blob de clave cifrado. Ese prefijo es lo que reconocen tanto hashcat como John; nunca se le pasa el archivo de clave en bruto directamente a ninguno de los dos.
Crackear una clave PEM clásica con hashcat
Para una clave clásica, el identificador de cifrado justo después de $sshng$ indica a hashcat qué modo usar:
| Prefijo del hash | modo hashcat |
|---|---|
$sshng$0$ | -m 22911 |
$sshng$6$ | -m 22921 |
$sshng$1$ / $sshng$3$ | -m 22931 |
$sshng$4$ | -m 22941 |
Ejecútalo como cualquier otro trabajo de hashcat:
hashcat -m 22911 hash.txt /usr/share/wordlists/rockyou.txt
Si la passphrase sigue un patrón conocido —una palabra seguida de un año, por ejemplo—, un ataque de máscara o un diccionario con reglas llegará mucho más rápido que un diccionario plano; mira la combinación de diccionario y reglas que realmente funciona.
Si hashcat devuelve una token length exception, no asumas primero que el hash está corrupto: comprueba si la clave es en realidad una clave openssh-key-v1 moderna. De eso trata la siguiente sección.
Cuando hashcat no puede ayudar: claves OpenSSH modernas
Los modos SSH documentados de hashcat (22911–22951) se diseñaron para el formato PEM/KDF MD5 antiguo. Una clave protegida con bcrypt-pbkdf —que, de nuevo, es la opción por defecto de toda clave generada por ssh-keygen desde 2018— todavía no tiene un modo estable. No malgastes tiempo de GPU forzando ese hash en alguno de los modos anteriores: la estructura de tokens no coincide y hashcat lo rechazará.
Aquí es donde John the Ripper demuestra su valor. El mismo resultado $sshng$ de ssh2john.py se crackea directamente en John:
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Si John no detecta automáticamente el formato correcto, lista lo que ofrece y elige la opción relacionada con SSH (el nombre exacto —ssh o ssh-ng— ha cambiado entre versiones jumbo):
john --list=formats | grep -i ssh
john --format=ssh-ng --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Como bcrypt-pbkdf es deliberadamente costoso, espera un rendimiento muy inferior al de una clave PEM clásica o al de un hash rápido sin sal: una palabra de diccionario corta sigue cayendo rápido, pero una passphrase larga y aleatoria es otra historia.
Para recordar
Identifica primero con qué contenedor estás tratando antes de elegir una herramienta: -----BEGIN RSA PRIVATE KEY----- y similares son el formato PEM antiguo que hashcat puede crackear directamente; -----BEGIN OPENSSH PRIVATE KEY----- es el contenedor bcrypt-pbkdf que, por ahora, necesita John the Ripper. En cualquier caso, ssh2john.py es la única forma de obtener un hash explotable a partir del archivo de clave, y la página de clave privada SSH del identificador de hash reúne todos los comandos una vez confirmado el modo.