;

Wenn Sie wie ich gerne zu WordCamps gehen, haben Sie wahrscheinlich schon gehört: „WordPress-Passwort-Hashing ist nicht sicher“oder in der technischsten Version: „…weil es md5 basiert“.

Wahr oder nicht, ein starkes Passwort-Hashing ist entscheidend für ein großes Ökosystem wie das WordPress-Ökosystem, das schon immer ein saftiges Ziel für Hacker war. Also habe ich beschlossen, mir das Hashing-System genauer anzusehen und zu versuchen, WordPress-Hashes von Grund auf neu zu knacken!

WordPress-Passwort-Hashes verstehen

Ich habe angefangen zu googeln und festgestellt, dass die meisten Informationen generisch und verwirrend sind. Viele Verweise auf die verwendeten PHP-Bibliotheken (portabler Hash von phpass), aber nichts wirklich Konkretes.

Ich habe mich für einen anderen Ansatz entschieden, ausgehend von einer Annahme:

Hashing ist ein Einwegprozess, aber WordPress ist auf irgendeine Weise in der Lage, Benutzer zu authentifizieren, die ihre Kennworteingabe mit dem in der Datenbank gespeicherten Hash abgleichen

Von dort aus begann ich, den Code zu überprüfen und fand die erste interessante Funktion: wp_check_password($password,$hash) die das Klartext-Passwort mit dem Hash vergleicht und true zurückgibt, wenn sie übereinstimmen.

1// presume the new style phpass portable hash.
2if ( empty( $wp_hasher ) ) {
3 require_once ABSPATH . WPINC . '/class-phpass.php';
4 // By default, use the portable hash from phpass.
5 $wp_hasher = new PasswordHash( 8, true );
6}
7
8$check = $wp_hasher->CheckPassword( $password, $hash );
9
10/** This filter is documented in wp-includes/pluggable.php */
11return apply_filters( 'check_password', $check, $password, $hash, $user_id );

Wenn wir den Code durchgehen, gelangen wir schnell zu CheckPassword, crypt_private und encode64, wo im Grunde die Magie passiert.

Um es kurz zu machen, crypt_private($password, $stored_hash) hasht das Passwort erneut, bevor es mit dem gespeicherten Hash verglichen wird. Wenn sie übereinstimmen, ist das Passwort korrekt und die Authentifizierung wird fortgesetzt. Was bedeutet, dass wir diese Funktion auch verwenden können, um den Hash zu knacken.

Hash Anatomie

Dies ist ein WordPress-Hash:

1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1

Der Einfachheit halber gehen wir davon aus, dass die Site PHP > 5 und den neuesten tragbaren Phpass-Hash verwendet, der das häufigste Setup ist.

Die ersten 3 Zeichen $P$ sind eine ID, die dem System mitteilt, welche Art von Hash wir haben.

Die Zeichennummer 3 (zählt von 0) wird verwendet, um zu bestimmen, wie oft md5() die Eingabezeichenfolge verarbeiten muss.

Zeichen von 4 bis 12 nPVO4gP9 sind das Salz, eine zufällige Zeichenfolge, die vor dem Hashing an das Passwort angehängt wird, um es zufälliger zu machen. Wenn Ihr Kennwort beispielsweise admin lautet, wird es in nPVO4gP9admin umgewandelt und dann gehasht.

Der verbleibende Teil des Hash JUMSAM1WlLTHPdH6EDj4e1 ist die tatsächliche Zufälligkeit, die durch das salt+Passwort erzeugt wird, das in einer undokumentierten encode64 -Funktion übergeben wird, die einige bitweise Operationen an der Eingabezeichenfolge ausführt und eine Ausgabe von 22 Zeichen zurückgibt.

Nicht so klar, äh? Bleib bei mir.

Bisher wissen wir:

  • der erste Teil des Hashs ist eine feste ID
  • der zweite ist ein einzelnes Zeichen, das als Zähler verwendet wird, ebenfalls fest
  • der dritte ist der Salz, gebunden an das Passwort
  • der letzte ist zufällig, generiert durch ’salt+pass‘ verarbeitet von der encode64-Funktion
1

So können wir die Logik – Salz + Passwort X-mal gehasht und in encode64 übergeben – neu schreiben, um einen Wörterbuch- oder Bruteforce-Angriff durchzuführen und den gleichen ‚letzten Teil‘ des Hashs zu erhalten, und das wäre ein erfolgreicher Hash-Crack!

In einem realen Szenario wären Hacker mehr daran interessiert, schwache Kennwörter zu finden, da sie eher wiederverwendet werden als zufällige, die häufig von einem Kennwortmanager generiert werden und daher standortspezifisch sind.

Umschreiben von encode64 mit Golang

Ich habe mich für Golang entschieden, weil es sehr schnell ist und wir all diese Geschwindigkeit benötigen, um große Kennwortwörterbücher zu berechnen.

Genau wie bei der WordPress-Verschlüsselungsprozedur nimmt das Skript den Hash und isoliert das Salz, dann komponiert es das Passwort (salt+pass) für jedes Passwort im Wörterbuch und md5-Hashing X Anzahl der Male, und wir haben gesehen, wie X bestimmt wird.

1itoa64 := "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
2hashloop := 1 << strings.Index(itoa64, string(hash)); // char n. 4 in the hash

Danach führt es eine Reihe von bitweisen Operationen für Bytes durch, die mit ord () in PHP erhalten wurden, die wir in Golang nicht benötigen, da wir bereits Bytewerte haben:

1itoa64 & 0x3f]

An diesem Punkt wurde mir klar, dass wir nicht einmal die ganze Saite finden müssen. Es reicht aus, ein paar Zeichen mit dem gesamten Passwort abzugleichen und das Skript leistungsfähiger zu machen! Also, aufgrund der Art des Hashing-Prozesses, wenn char n. 0 / 4 / 8 … ja, das als Eingabe übergebene Passwort ist korrekt.

Und BOOM, wir haben den Hash geknackt:

1wphashcrash '$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1' Dev/wphashcrash/dict.txt
2$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1 admin
32020/05/30 12:44:15 Executed in 0.000221

Der Code ist wie üblich auf GitHub – https://github.com/francescocarlucci/wphashcrash – und im Moment ist das Skript ein POC und erhält nur einen einzigen Passwort-Hash als Eingabe und den Pfad zum Passwort-Wörterbuch.

Ich habe bereits in der Readme einige Verbesserungen skizziert, die schön wären und die ich wahrscheinlich in Zukunft hinzufügen werde.

Wenn Sie wirklich versuchen möchten, eine Liste von Hashes zu hacken, können Sie sie verzweigen oder das Skript einfach in eine Bash-for-Schleife einschließen.

Secuirty considerations

An dieser Stelle denke ich, dass es klar genug ist, dass ein Angreifer, wenn er Zugriff auf die Datenbank einer WordPress-Site erhält, im Grunde jedes schwache Passwort knacken kann.

Diese unglückliche, vor allem, weil:

  • SQL Injection ist in WordPress-Plugins nicht so selten
  • RCE gewährt höchstwahrscheinlich auch Zugriff auf die Datenbank
  • Das WordPress-Ökosystem ist ein riesiges Gebiet für die Arbeit von Freiberuflern und findet häufig alte / unbenutzte wp-Admin- und FTP-Konten, die für temporäre Zwecke erstellt wurden

Dieser letzte Punkt, kombiniert mit der Benutzeraufzählung, die ein häufiges Problem von WordPress ist, lässt die Tür offen, um mit gestohlenen / verpfändeten Administratoranmeldeinformationen Zugriff auf die Datenbank zu erhalten.

Darüber hinaus erzwingen viele Websites keine starken Passwörter, um die Benutzererfahrung nicht zu beeinträchtigen, und ich habe direkte Erfahrung in einem der genannten Punkte.

Sobald eine Website kompromittiert ist, können Angreifer mit schwachen Hashes andere Benutzerkonten auf anderen Websites kompromittieren, wenn sie dazu neigen, Kennwörter wiederzuverwenden, und wir wissen, dass sie dies tun.

Haben wir Lösungen?

Meine Forschung ging nicht so weit, ich wollte nur sehen, wie man WordPress-Hashes bricht.

Bcrypt ist bekanntermaßen eine stärkere Hashing-Methode als md5, und es gibt ein vorhandenes Plugin, das bcrypt verwendet und alle Kernfunktionen ersetzt, die für die Verarbeitung von Passwörtern erforderlich sind:

  • wp_check_password()
  • wp_hash_password()
  • wp_set_password()

Und natürlich können Sie als Entwickler Ihre eigene Lösung schreiben, aber ich glaube, dass dies ein Problem ist, das auf Kernebene behoben werden muss, um eine große Akzeptanz anzustreben.

Schlussbemerkung

Es gibt viele Tools zum Knacken von Hashes, wie Hashcat und John The Ripper, die möglicherweise noch leistungsfähiger sind, aber auch hier besteht der Umfang dieser Forschung darin, die WordPress-Hash-Struktur zu verstehen und von Grund auf neu zu knacken.

Danke fürs Lesen.5051 9922 frenxi 5051

Write a Comment

Deine E-Mail-Adresse wird nicht veröffentlicht.