Hash in der /etc/shadow: Unterschied zwischen den Versionen
(→Hash) |
|||
| (12 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
| Zeile 10: | Zeile 10: | ||
<pre> | <pre> | ||
| − | $y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB | + | xinux:$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB |
</pre> | </pre> | ||
| Zeile 46: | Zeile 46: | ||
=== Hash === | === Hash === | ||
| − | Das letzte Feld (<code>vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB | + | Das letzte Feld (<code>vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB</code>) ist das eigentliche '''Ergebnis''' der Hash-Funktion, berechnet aus Passwort, Salt und Parametern. Der Vorgang ist eine Einwegfunktion – aus dem Hash lässt sich das Passwort nicht direkt zurückrechnen. |
| + | |||
| + | === Mit Perl testen === | ||
| + | |||
| + | <pre> | ||
| + | HASH='$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB' | ||
| + | for PW in supper trottel zinch; do | ||
| + | echo -n "$PW: " | ||
| + | perl -e 'print crypt($ARGV[0], $ARGV[1]), "\n"' "$PW" "$HASH" | ||
| + | done | ||
| + | </pre> | ||
| + | |||
| + | '''Was <code>crypt($ARGV[0], $ARGV[1])</code> mit den Parametern macht:''' | ||
| + | |||
| + | * <code>$ARGV[0]</code> (das Passwort) und <code>$ARGV[1]</code> (der komplette <code>$HASH</code>-String) werden an Perls <code>crypt()</code>-Funktion übergeben, die direkt die System-''libcrypt'' (glibc) aufruft. | ||
| + | * <code>crypt()</code> liest aus dem zweiten Argument automatisch nur den vorderen Teil bis zum dritten <code>$</code> aus (<code>$y$j9T$GThSkReZ3cOQQojV/asp00</code>) – Algorithmus-ID, Cost-Parameter und Salt. Der Rest (der eigentliche Hash-Teil hinter dem letzten <code>$</code>) wird ignoriert. | ||
| + | * Mit diesen ausgelesenen Werten hasht <code>crypt()</code> das übergebene Passwort '''neu''', exakt nach demselben Verfahren (gleicher Algorithmus, gleicher Cost-Faktor, gleiches Salt) wie beim Original. | ||
| + | * Zurückgegeben wird der komplette neue Hash-String im selben Format – der wird dann mit dem Original-Hash verglichen. | ||
| + | ===Mit John testen=== | ||
| + | *sudo apt install john | ||
| + | *echo 'xinux:$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB' > xinux-hash.txt | ||
| + | *john --format=crypt --wordlist=bad-passwords xinux-hash.txt | ||
| + | *john --show --format=crypt xinux-hash.txt | ||
| + | xinux:zinch | ||
Aktuelle Version vom 12. August 2026, 06:57 Uhr
Der crypt-Hash im Detail
Ein Passwort-Hash in /etc/shadow ist kein einzelner Wert, sondern setzt sich aus mehreren Teilen zusammen, getrennt durch $-Zeichen:
$id$param$salt$hash
Beispiel:
xinux:$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB
Algorithmus-ID
Das erste Feld (y) gibt an, welcher Hash-Algorithmus verwendet wurde. yescrypt ist auf aktuellen Linux-Systemen (z. B. Debian, Fedora, Rocky Linux) der Standard.
| ID | Algorithmus |
|---|---|
$1$ |
MD5 (veraltet, unsicher) |
$5$ |
SHA-256 |
$6$ |
SHA-512 |
$2b$ |
bcrypt |
$y$ |
yescrypt (aktueller Standard) |
Parameter (Cost-Faktor)
Das zweite Feld (j9T) kodiert die Kostenparameter des Algorithmus – u. a. wie viel Speicher und Rechenzeit pro Hash-Berechnung nötig sind. Ein höherer Cost-Faktor macht das Verfahren absichtlich langsamer, um Bruteforce-Angriffe zu erschweren.
Salt
Das dritte Feld (GThSkReZ3cOQQojV/asp00) ist das Salt – eine zufällige Zeichenfolge, die bei jedem passwd-Aufruf neu erzeugt wird.
- Wird zusammen mit dem Passwort gehasht
- Steht offen sichtbar im Hash (ist kein Geheimnis)
- Sorgt dafür, dass zwei User mit identischem Passwort unterschiedliche Hashes erhalten
- Verhindert Angriffe mit vorberechneten Rainbow-Tables
Hash
Das letzte Feld (vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB) ist das eigentliche Ergebnis der Hash-Funktion, berechnet aus Passwort, Salt und Parametern. Der Vorgang ist eine Einwegfunktion – aus dem Hash lässt sich das Passwort nicht direkt zurückrechnen.
Mit Perl testen
HASH='$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB'
for PW in supper trottel zinch; do
echo -n "$PW: "
perl -e 'print crypt($ARGV[0], $ARGV[1]), "\n"' "$PW" "$HASH"
done
Was crypt($ARGV[0], $ARGV[1]) mit den Parametern macht:
$ARGV[0](das Passwort) und$ARGV[1](der komplette$HASH-String) werden an Perlscrypt()-Funktion übergeben, die direkt die System-libcrypt (glibc) aufruft.crypt()liest aus dem zweiten Argument automatisch nur den vorderen Teil bis zum dritten$aus ($y$j9T$GThSkReZ3cOQQojV/asp00) – Algorithmus-ID, Cost-Parameter und Salt. Der Rest (der eigentliche Hash-Teil hinter dem letzten$) wird ignoriert.- Mit diesen ausgelesenen Werten hasht
crypt()das übergebene Passwort neu, exakt nach demselben Verfahren (gleicher Algorithmus, gleicher Cost-Faktor, gleiches Salt) wie beim Original. - Zurückgegeben wird der komplette neue Hash-String im selben Format – der wird dann mit dem Original-Hash verglichen.
Mit John testen
- sudo apt install john
- echo 'xinux:$y$j9T$GThSkReZ3cOQQojV/asp00$vkzM8oX6944ruaPuQ9EJT1CEZiQ1d/WA1MXOkp1ULtB' > xinux-hash.txt
- john --format=crypt --wordlist=bad-passwords xinux-hash.txt
- john --show --format=crypt xinux-hash.txt
xinux:zinch