jeśli lubisz chodzić na Wordcampy tak jak ja, prawdopodobnie słyszałeś już to: „hashowanie haseł WordPress nie jest bezpieczne”, lub w najbardziej technicznej wersji:”…ponieważ jest oparty na md5″.
Prawda czy nie, silne hashowanie haseł ma kluczowe znaczenie dla dużego ekosystemu, takiego jak WordPress, który zawsze był soczystym celem dla hakerów. Postanowiłem więc przyjrzeć się bliżej systemowi haszowania i spróbować złamać hash WordPress od podstaw!
zrozumienie hashów haseł WordPress
zacząłem googlować i odkryłem, że większość informacji jest ogólna i myląca. Wiele odniesień do używanych bibliotek PHP (portable hash z phpass), ale nic konkretnego.
postanowiłem przyjąć inne podejście zaczynając od założenia:
hashing jest procesem jednokierunkowym, ale WordPress jest w stanie uwierzytelnić użytkowników pasujących do ich hasła z Hashem zapisanym w bazie danych
stamtąd zacząłem sprawdzać kod i znalazłem pierwszą ciekawą funkcję: wp_check_password($password,$hash)
, która porównuje zwykłe hasło tekstowe z Hashem i zwraca true, jeśli się zgadzają.
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 );
przechodząc przez kod, szybko doprowadza nas do CheckPassword
, crypt_private
i encode64
, co w zasadzie jest miejscem, w którym dzieje się magia.
krótko mówiąc, crypt_private($password, $stored_hash)
ponownie hashuje hasło, zanim zostanie porównane do przechowywanego skrótu. Jeśli pasują, hasło jest poprawne i uwierzytelnianie trwa. Co oznacza, że możemy również użyć tej funkcji do złamania skrótu.
hash anatomy
to jest hash WordPress:
1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1
dla uproszczenia Zakładamy, że strona używa PHP>5 i najnowszego przenośnego skrótu phpass, który jest najczęstszą konfiguracją.
pierwsze 3 znaki $P$
są identyfikatorem, informującym system jakiego rodzaju Oh hash mamy.
liczba znaków 3 (licząc od 0) jest używana do określenia, ile razy md5() ma przetworzyć łańcuch wejściowy.
znaki od 4 do 12 nPVO4gP9
to sól, która jest losowym ciągiem dodawanym do hasła przed hashowaniem, aby nadać mu większą losowość. Na przykład, jeśli Twoje hasło jest admin, zostanie zamienione na nPVO4gP9admin, a następnie haszowane.
pozostała część skrótu JUMSAM1WlLTHPdH6EDj4e1
to prawdziwa losowość, wygenerowana przez hasło salt+przekazane w nieudokumentowanej funkcji encode64
, która wykonuje pewne operacje bitowe na łańcuchu wejściowym i zwraca wyjście 22 znaków.
nie tak jasno? Trzymaj się mnie.
jak na razie wiemy:
- pierwsza część skrótu jest stałym id
- druga jest pojedynczym znakiem używanym jako licznik, również naprawionym
- trzecia jest solą, powiązaną z hasłem
- ostatnia jest losowa, generowana przez 'salt + pass’ przetwarzane przez funkcję encode64
1
możemy więc ponownie napisać logikę-salt+hasło hashowane X razy i przekazane w encode64 – aby wykonać atak słownikowy lub bruteforce, i uzyskać tę samą „ostatnią część” skrótu, a to byłoby udane pęknięcie hash!
w prawdziwym scenariuszu hakerzy będą bardziej zainteresowani znalezieniem słabych haseł, ponieważ są one bardziej prawdopodobne, że zostaną ponownie użyte, zamiast losowych, które są często generowane przez menedżera haseł i tak specyficzne dla witryny.
przepisywanie encode64 za pomocą golang
zdecydowałem się na golang, ponieważ jest bardzo szybki i potrzebujemy całej tej prędkości, aby obliczyć Duże słowniki haseł.
podobnie jak w procedurze szyfrowania WordPress, skrypt pobiera hash i izoluje sól, a następnie komponuje hasło (salt+pass) próbując każdego hasła w Słowniku i md5-hashowanie x liczba razy, a widzieliśmy, jak X jest określana.
1itoa64 := "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 2hashloop := 1 << strings.Index(itoa64, string(hash)); // char n. 4 in the hash
Done that, wykonuje szereg operacji bitowych na bajtach uzyskanych za pomocą ord () w PHP, których nie potrzebujemy w golangu, ponieważ mamy już wartości bajtów:
1itoa64 & 0x3f]
w tym momencie zdałem sobie sprawę, że nie musimy nawet znaleźć całego Sznurka. Wystarczy dopasować kilka znaków, aby dopasować całe hasło i uczynić skrypt bardziej wydajnym! Tak więc, ze względu na charakter procesu mieszania, jeśli znak n. 0 / 4 / 8 … pasuje, hasło przekazane jako wejście jest poprawne.
i BUM, złamaliśmy hash:
1wphashcrash '$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1' Dev/wphashcrash/dict.txt 2$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1 admin 32020/05/30 12:44:15 Executed in 0.000221
kod jest jak zwykle na Githubie – https://github.com/francescocarlucci/wphashcrash – i w tej chwili skrypt jest POC i dostaje tylko jeden hash hasła jako wejście i ścieżkę do słownika haseł.
już nakreśliłem w readme kilka usprawnień, które byłoby miło mieć i prawdopodobnie dodam w przyszłości.
jeśli naprawdę chcesz spróbować zhakować listę skrótów, możesz ją forkować lub po prostu zawinąć skrypt w pętlę bash for.
Secuirty considerations
w tym momencie myślę, że jest wystarczająco jasne, że jeśli atakujący uzyska dostęp do bazy danych w witrynie WordPress, może w zasadzie złamać każde słabe hasło.
to niefortunne, zwłaszcza, że:
- SQL Injection nie jest tak rzadki w wtyczkach WordPress
- RCE najprawdopodobniej przyzna dostęp do DB
- ekosystem WordPress jest ogromnym terytorium dla pracy freelancera i jest bardzo powszechny w znajdowaniu starych/nieużywanych kont wp-admin i FTP, utworzonych dla tymczasowych potrzeb
ten ostatni punkt, w połączeniu z wyliczeniem użytkowników, które, pozostawia otwarte drzwi do uzyskania dostępu do bazy danych za pomocą skradzionych/zastawionych poświadczeń administratora.
ponadto wiele stron internetowych nie wymusza silnych haseł, aby nie zaszkodzić doświadczeniu użytkownika, a ja mam bezpośrednie doświadczenie w żadnym z wymienionych punktów.
gdy witryna jest zagrożona, posiadanie słabych skrótów pozwala atakującym na narażenie innych kont użytkowników na innych stronach, jeśli mają tendencję do ponownego użycia haseł, a my wiemy, że tak.
czy mamy rozwiązania?
moje badania nie poszły tak daleko, chciałem tylko zobaczyć, jak złamać hashy WordPress.
Bcrypt jest znana jako silniejsza metoda haszowania w porównaniu do md5, a istnieje istniejąca wtyczka, która używa bcrypt i zastępuje wszystkie podstawowe funkcje potrzebne do obsługi haseł:
- wp_check_password ()
- wp_hash_password ()
- wp_set_password()
i oczywiście możesz napisać własne rozwiązanie jako programista, ale uważam, że jest to problem do naprawienia na poziomie podstawowym, aby dążyć do dużej adopcji.
ostatnia uwaga
istnieje wiele narzędzi do łamania skrótów, takich jak Hashcat i John the Ripper, które mogą być jeszcze bardziej wydajne, ale ponownie, zakres tych badań polega na zrozumieniu struktury hash WordPress i złamaniu jej od podstaw.
dzięki za przeczytanie.
frenxi