ha szívesen jár a WordCamps – ba, mint én, akkor valószínűleg ezt már hallotta: “a WordPress jelszó kivonatolása nem biztonságos”, vagy a legtechnikaibb változatban: “…mert md5 alapú”.
igaz vagy sem, az erős jelszó-kivonatolás elengedhetetlen egy olyan nagy ökoszisztéma számára, mint a WordPress, amely mindig is lédús célpont volt a hackerek számára. Tehát úgy döntöttem, hogy közelebbről megvizsgálom a hash rendszert, és megpróbálom feltörni a WordPress hash-okat a semmiből!
a WordPress jelszó hash-ok megértése
elkezdtem Google-t keresni, és rájöttem, hogy a legtöbb információ általános és zavaros. Sok hivatkozás a használt PHP könyvtárakra (hordozható hash a phpass-tól), de semmi igazán konkrét.
úgy döntöttem, hogy más megközelítést alkalmazok egy feltételezés alapján:
a kivonatolás egyirányú folyamat, de a WordPress valahogyan képes hitelesíteni azokat a felhasználókat, akik a jelszó bevitelét az adatbázisban tárolt kivonattal egyeztetik
innen kezdtem ellenőrizni a kódot, és megtaláltam az első érdekes funkciót: wp_check_password($password,$hash)
amely összehasonlítja az egyszerű szöveges jelszót a kivonattal, és true értéket ad vissza, ha azok egyeznek.
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 );
a kód segítségével gyorsan eljuthatunk a CheckPassword
, crypt_private
és encode64
pontokhoz, ahol a varázslat történik.
hosszú történet rövid, crypt_private($password, $stored_hash)
újra kivonatolja a jelszót, mielőtt megkapja, mint a tárolt hash. Ha megegyeznek, a jelszó helyes, és a hitelesítés folytatódik. Ami azt jelenti, hogy ezt a függvényt is felhasználhatjuk a hash feltörésére.
hash anatómia
ez egy WordPress hash:
1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1
az egyszerűség kedvéért feltételezzük, hogy az oldal PHP>5-öt és a legújabb phpass portable hash-ot használja, ami a leggyakoribb beállítás.
az első 3 karakter $P$
egy azonosító, amely megmondja a rendszernek, hogy milyen oh hash van.
a 3.karakter (0-tól számítva) annak meghatározására szolgál, hogy az md5() hányszor kell feldolgoznia a bemeneti karakterláncot.
a 4-től 12-ig terjedő karakterek nPVO4gP9
a só, amely egy véletlenszerű karakterlánc, amelyet a jelszóhoz csatolnak a kivonatolás előtt, hogy nagyobb véletlenszerűséget biztosítson. Például, ha a jelszó admin, akkor az nPVO4gP9admin lesz, majd kivonatolva.
a JUMSAM1WlLTHPdH6EDj4e1
hash fennmaradó része a valódi véletlenszerűség, amelyet a salt+jelszó generál egy nem dokumentált encode64
függvényben, amely bitenként hajt végre műveleteket a bemeneti karakterláncon, és 22 karakter kimenetet ad vissza.
nem olyan világos, mi? Maradj velem.
eddig tudjuk:
- a hash első része rögzített azonosító
- a második egyetlen számlálóként használt karakter, szintén rögzített
- a harmadik a só, a jelszóhoz kötve
- az utolsó véletlenszerű, amelyet a ‘salt+pass’ generál, amelyet az encode64 függvény dolgoz fel
1
tehát újraírhatjuk a logikát – salt+password hashed X times and password in encode64-egy szótár vagy bruteforce támadás végrehajtásához, és megkaphatjuk a hash ugyanazon ‘utolsó részét’, és ez sikeres hash repedés lenne!
egy valós forgatókönyv szerint a hackerek jobban érdekelnék a gyenge jelszavak megtalálását, mert nagyobb valószínűséggel használják őket újra, nem pedig véletlenszerűen, amelyeket gyakran egy jelszókezelő generál, és így helyspecifikus.
az encode64 átírása a golang használatával
úgy döntöttem, hogy a golang-ot választom, mert nagyon gyors, és ekkora sebességre van szükségünk a nagy jelszószótárak kiszámításához.
csakúgy, mint a WordPress titkosítási eljárás, a script veszi a hash és izolálja a sót, majd komponálja a jelszót (salt+pass) próbál minden jelszót a szótárban és md5-hash X hányszor, és láttuk, hogyan X határozza meg.
1itoa64 := "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 2hashloop := 1 << strings.Index(itoa64, string(hash)); // char n. 4 in the hash
kész, hogy egy sor bitenkénti műveletet hajt végre a PHP ord() használatával kapott bájtokon, amelyekre nincs szükségünk golangban, mivel már vannak bájtértékeink:
1itoa64 & 0x3f]
ezen a ponton rájöttem, hogy nem is kell megtalálnunk az egész karakterláncot. Elég, hogy megfeleljen néhány karaktert, hogy megfeleljen az egész jelszót, és a script több teljesítményt! Tehát a hasítási folyamat jellege miatt, ha a char n. 0 / 4 / 8 … egyezik, a bevitt jelszó helyes.
és bumm, feltörtük a hash-ot:
1wphashcrash '$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1' Dev/wphashcrash/dict.txt 2$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1 admin 32020/05/30 12:44:15 Executed in 0.000221
a kód a Githubon szokásos – https://github.com/francescocarlucci/wphashcrash – és jelenleg a szkript POC, és csak egy jelszó kivonatot kap bemenetként, valamint a jelszó szótár elérési útját.
már felvázoltam a readme-ben néhány olyan fejlesztést, amely jó lenne, és valószínűleg hozzáadom a jövőben.
ha tényleg meg akarod próbálni feltörni a hash-ek listáját, akkor villázhatod, vagy csak becsomagolhatod a szkriptet egy bash for loop-ba.
Secuirty considerations
ezen a ponton azt hiszem, elég világos, hogy ha egy támadó hozzáférést kap az adatbázishoz egy WordPress webhelyen, akkor alapvetően minden gyenge jelszót feltörhet.
ez sajnálatos, különösen azért, mert:
- SQL Injection nem olyan ritka a WordPress plugins
- RCE is valószínűleg hozzáférést biztosít a DB
- WordPress ökoszisztéma egy hatalmas terület szabadúszó munkáját, és nagyon gyakori, hogy megtalálják a régi/fel nem használt wp-admin és FTP fiókok, létre ideiglenes szükségletek
ez az utolsó pont, kombinálva a felhasználó felsorolása, amely a WordPress közös kérdés, nyitva hagyja az ajtót, hogy hozzáférjen a DB segítségével lopott/zálogba admin hitelesítő adatokat.
ezen felül sok weboldal nem kényszerít erős jelszavakat, hogy ne sértse meg a felhasználói élményt, és közvetlen tapasztalatom van az említett pontok bármelyikében.
ha egy webhely veszélybe kerül, a gyenge hash-ok tárolása lehetővé teszi a támadók számára, hogy más webhelyeken más felhasználói fiókokat veszélyeztessenek, ha hajlamosak újra használni a jelszavakat, és tudjuk, hogy igen.
vannak megoldásaink?
kutatásom nem ment olyan messzire, csak azt akartam látni, hogyan lehet megtörni a WordPress hash-okat.
a Bcrypt ismert, hogy erősebb kivonatolási módszer az md5-hez képest, és létezik egy meglévő plugin, amely a bcrypt-t használja, és helyettesíti a jelszavak kezeléséhez szükséges összes alapvető funkciót:
- wp_check_password ()
- wp_hash_password ()
- wp_set_password()
természetesen fejlesztőként is megírhatja saját megoldását, de úgy gondolom, hogy ezt a problémát alapvető szinten kell megoldani, hogy a nagy örökbefogadásra törekedjünk.
záró megjegyzés
számos eszköz létezik a hash-ek feltörésére, mint például a Hashcat és a John the Ripper, amelyek még jobban teljesítenek, de ismét a kutatás célja a WordPress hash szerkezetének megértése és a semmiből történő feltörése.
köszönöm az olvasást.
frenxi