SSH-Private-Key-Passphrasen mit hashcat und John the Ripper knacken
Extrahiere den Hash eines verschlüsselten id_rsa mit ssh2john, wähle den richtigen hashcat-Modus für PEM-Schlüssel, und erfahre, wann nur John moderne OpenSSH-Schlüssel knackt.
Ein verschlüsselter SSH-Private-Key ist letztlich nur ein weiteres passwortgeschütztes Geheimnis und reduziert sich wie jedes andere auf dieselbe Frage: Hash extrahieren, das richtige Tool und den richtigen Modus wählen, eine Wortliste laufen lassen. Die Besonderheit bei SSH-Schlüsseln: Hinter demselben Banner -----BEGIN ... PRIVATE KEY----- verstecken sich zwei sehr unterschiedliche Formate, und aktuell kann hashcat nur eines davon anfassen.
Zwei Schlüsselformate, zwei unterschiedliche Probleme
Ältere Schlüssel — alles, was mit ssh-keygen -m PEM erzeugt wurde, oder was Tools liefern, die noch standardmäßig das traditionelle Format verwenden — sind PEM-Dateien im OpenSSL-Stil. Die Passphrase leitet über ein einfaches MD5-basiertes KDF einen symmetrischen Schlüssel ab, der dann den eingebetteten RSA-/DSA-/EC-Schlüssel mit DES, 3DES oder AES-CBC entschlüsselt — je nachdem, was der Header angibt.
Seit OpenSSH 7.8 (2018) schreibt ssh-keygen standardmäßig den neueren openssh-key-v1-Container für jeden Schlüsseltyp, einschließlich des inzwischen verbreiteten id_ed25519. Das einzige KDF, das dieses Format unterstützt, ist bcrypt-pbkdf — bewusst langsamer und speicherintensiver als das alte MD5-Schema. Gut für dich, wenn es dein Schlüssel ist, schlecht für einen Angreifer, und der Grund, warum viele „ich habe hashcat auf meinen Schlüssel losgelassen und es kam ein Fehler" sich als Formatproblem und nicht als Cracking-Problem entpuppen.
Den Hash mit ssh2john extrahieren
Beide Formate laufen über dasselbe Tool. ssh2john.py liegt bei der John-the-Ripper-Jumbo-Distribution bei (unter Kali meist unter /usr/share/john/ssh2john.py oder /opt/john/ssh2john.py) und prüft selbst den Schlüssel-Header, um zu entscheiden, wie er geparst werden muss:
python3 /usr/share/john/ssh2john.py id_rsa > hash.txt
Das Ergebnis ist eine einzelne Zeile mit dem Präfix $sshng$, gefolgt von einer Cipher-ID, den KDF-Parametern und dem verschlüsselten Key-Blob. Dieses Präfix erkennen hashcat und John — die rohe Schlüsseldatei selbst wird nie direkt an einen der beiden übergeben.
Einen klassischen PEM-Schlüssel mit hashcat knacken
Bei einem klassischen Schlüssel verrät die Cipher-ID direkt nach $sshng$, welchen Modus hashcat braucht:
| Hash-Präfix | hashcat-Modus |
|---|---|
$sshng$0$ | -m 22911 |
$sshng$6$ | -m 22921 |
$sshng$1$ / $sshng$3$ | -m 22931 |
$sshng$4$ | -m 22941 |
Starte ihn wie jeden anderen hashcat-Job:
hashcat -m 22911 hash.txt /usr/share/wordlists/rockyou.txt
Folgt die Passphrase einem bekannten Muster — etwa einem Wort plus Jahreszahl —, kommt man mit einem Maskenangriff oder einer mit Regeln erweiterten Wortliste deutlich schneller zum Ziel als mit einem reinen Wörterbuchlauf; siehe die Wortlisten- und Regeln-Kombination, die wirklich funktioniert.
Meldet hashcat eine token length exception, geh nicht gleich davon aus, der Hash sei defekt — prüfe zuerst, ob es sich nicht in Wahrheit um einen modernen openssh-key-v1-Schlüssel handelt. Darum geht es im nächsten Abschnitt.
Wenn hashcat nicht weiterhilft: moderne OpenSSH-Schlüssel
Die dokumentierten SSH-Modi von hashcat (22911–22951) wurden für das alte PEM-/MD5-KDF-Format gebaut. Ein mit bcrypt-pbkdf geschützter Schlüssel — der, wie gesagt, seit 2018 die Standardeinstellung jedes von ssh-keygen erzeugten Schlüssels ist — ist noch nicht in einem stabilen Modus abgedeckt. Verschwende keine GPU-Zeit damit, diesen Hash in einen der obigen Modi zu zwingen; die Token-Struktur passt nicht, und hashcat weist ihn zurück.
Hier spielt John the Ripper seine Stärke aus. Dieselbe $sshng$-Ausgabe von ssh2john.py lässt sich direkt in John knacken:
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Erkennt John das richtige Format nicht automatisch, lass dir die verfügbaren Formate auflisten und wähle das SSH-bezogene aus (der genaue Name — ssh oder ssh-ng — hat sich zwischen Jumbo-Versionen schon geändert):
john --list=formats | grep -i ssh
john --format=ssh-ng --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
Da bcrypt-pbkdf bewusst teuer ist, solltest du mit einem deutlich geringeren Durchsatz rechnen als bei einem klassischen PEM-Schlüssel oder einem ungesalzenen schnellen Hash — ein kurzes Wörterbuchwort fällt trotzdem schnell, eine lange zufällige Passphrase ist eine ganz andere Geschichte.
Zum Mitnehmen
Identifiziere zuerst den Container, mit dem du es zu tun hast, bevor du ein Tool wählst: -----BEGIN RSA PRIVATE KEY----- und Verwandte sind das alte PEM-Format, das hashcat direkt knacken kann; -----BEGIN OPENSSH PRIVATE KEY----- ist der bcrypt-pbkdf-Container, der derzeit John the Ripper braucht. So oder so ist ssh2john.py der einzige Weg, aus der Schlüsseldatei einen knackbaren Hash zu gewinnen, und die SSH-Private-Key-Seite des Hash-Identifiers listet den vollständigen Befehlssatz, sobald der passende Modus feststeht.