;

pokud vás baví chodit na WordCamps jako já, pravděpodobně jste to už slyšeli: „hashování hesel WordPress není bezpečné“ nebo v nejvíce technické verzi: „…protože je založen na md5“.

pravda nebo ne, silné hashování hesel je zásadní pro velký ekosystém, jako je WordPress, který byl vždy šťavnatým cílem hackerů. Tak, rozhodl jsem se blíže podívat na hashovací systém a pokusit se prasknout hashe WordPress od nuly!

porozumění heslům WordPress hashe

začal jsem dělat nějaké googling a zjistil jsem, že většina informací je obecná a matoucí. Spousta odkazů na použité knihovny PHP( přenosný hash z phpassu), ale nic konkrétního.

rozhodl jsem se zvolit jiný přístup, počínaje předpokladem:

hashování je jednosměrný proces, ale WordPress je nějakým způsobem schopen ověřit uživatele odpovídající zadání hesla s hash uloženým v databázi

odtud jsem začal kontrolovat kód a našel první zajímavou funkci: wp_check_password($password,$hash) který porovnává heslo prostého textu s hash a vrací true, pokud se shodují.

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 );

když procházíme kódem, rychle nás přivede k CheckPassword, crypt_private a encode64, což je v podstatě místo, kde se kouzlo děje.

dlouhý příběh krátký, crypt_private($password, $stored_hash) znovu hashuje heslo dříve, než se porovná s uloženým hash. Pokud se shodují, heslo je správné a ověřování pokračuje. Což znamená, že můžeme také použít tuto funkci k prasknutí hash.

hash anatomy

Toto je WordPress hash:

1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1

pro jednoduchost budeme předpokládat, že web používá PHP>5 a nejnovější přenosný hash phpass, což je nejběžnější nastavení.

první 3 znaky $P$ jsou ID, které říká systému, jaký druh oh hash máme.

znak číslo 3 (počítání od 0) se používá k určení, kolikrát md5() musí zpracovat vstupní řetězec.

znaky od 4 do 12 nPVO4gP9 jsou sůl, což je náhodný řetězec připojený k heslu před hashováním, aby mu dal větší náhodnost. Pokud je například vaše heslo admin, změní se na nPVO4gP9admin a poté se hashuje.

zbývající část pro hash JUMSAM1WlLTHPdH6EDj4e1 je skutečná náhodnost, generovaná heslem salt+předaným v nezdokumentované funkci encode64, která provádí některé bitové operace na vstupním řetězci a vrací výstup 22 znaků.

není to tak jasné, uh? Drž se mě.

zatím víme:

  • první část hash je pevné id
  • druhý je jediný znak používaný jako čítač, také pevný
  • třetí je sůl, vázaná na heslo
  • poslední je náhodný, generovaný „salt + pass“ zpracovaným funkcí encode64
1

takže můžeme znovu napsat logiku-salt + heslo hash X krát a předán v encode64-provést slovník nebo bruteforce útok, a získat stejný ‚poslední část‘ hash a to by bylo úspěšné hash crack!

v reálném scénáři a hackeři by se více zajímali o nalezení slabých hesel, protože je pravděpodobnější, že budou znovu použita, místo náhodných, která jsou často generována správcem hesel, a tak specifická pro web.

přepisování encode64 pomocí golang

rozhodl jsem se jít s golang, protože je velmi rychlý, a my potřebujeme všechnu tu rychlost pro výpočet velkých slovníků hesel.

stejně jako v šifrovacím postupu WordPress skript vezme hash a izoluje sůl, pak složí heslo (salt + pass), které se pokouší o každé heslo ve slovníku A md5-hash X kolikrát, a viděli jsme, jak je X určeno.

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

provádí řadu bitových operací na bajtech získaných pomocí ord () v PHP, které v golangu nepotřebujeme, protože již máme hodnoty bajtů:

1itoa64 & 0x3f]

v tuto chvíli jsem si uvědomil, že ani nemusíme najít celý řetězec. To je dost, aby odpovídaly několik znaků, aby odpovídaly celé heslo a aby skript výkonnější! Takže vzhledem k povaze procesu hašování, pokud char n. 0 / 4 / 8 … odpovídá, heslo předané jako vstup je správné.

a BUM, popraskali jsme hash:

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

kód je jako obvykle na Githubu – https://github.com/francescocarlucci/wphashcrash – a v současné době je skript POC a jako vstup získá pouze jedno heslo hash a cestu ke slovníku hesel.

v readme jsem již nastínil některá vylepšení, která by bylo hezké mít, a pravděpodobně přidám v budoucnu.

pokud se opravdu chcete pokusit hacknout seznam hashů, můžete jej rozvětvit nebo jen zabalit skript do smyčky.

bezpečné úvahy

v tomto okamžiku si myslím, že je dostatečně jasné, že pokud útočník získá přístup k databázi na webu WordPress, může v podstatě prolomit každé slabé heslo.

toto nešťastné, zejména proto, že:

  • SQL Injection není tak vzácný v pluginech WordPress
  • RCE také s největší pravděpodobností udělí přístup k DB
  • WordPress ekosystém je obrovské území pro práci na volné noze a je velmi běžné najít staré/nepoužívané účty wp-admin a FTP vytvořené pro dočasné potřeby

tento poslední bod v kombinaci s výčtem uživatelů, který je běžným problémem WordPress, ponechává dveře otevřené pro získání přístupu k DB pomocí ukradených/zastavených pověření administrátora.

kromě toho mnoho webových stránek nevynucuje silná hesla, aby nepoškodilo uživatelskou zkušenost, a mám přímé zkušenosti s některým z uvedených bodů.

jakmile je web ohrožen, ukládání slabých hashů umožňuje útočníkům kompromitovat jiné uživatelské účty na jiných webech, pokud mají tendenci znovu používat hesla a my víme, že ano.

máme řešení?

můj výzkum nešel tak daleko, chtěl jsem jen vidět, jak rozbít hashe WordPress.

Bcrypt je známo, že je silnější hashovací metoda ve srovnání s md5, a existuje existující plugin, který používá bcrypt a nahrazuje všechny základní funkce potřebné pro zpracování hesel:

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

a samozřejmě můžete napsat své vlastní řešení jako vývojář, ale věřím, že je to problém, který je třeba vyřešit na základní úrovni, aby se zaměřil na velké přijetí.

závěrečná poznámka

existuje mnoho nástrojů k prasknutí hashů, jako je Hashcat a John Rozparovač, které mohou být ještě výkonnější, ale opět je cílem tohoto výzkumu pochopit strukturu hash WordPress a praskání od nuly.

Díky za přečtení.

frenxi

Write a Comment

Vaše e-mailová adresa nebude zveřejněna.