dacă vă place să mergeți la WordCamps așa cum fac eu, probabil că ați auzit deja acest lucru: „hashing-ul parolei WordPress nu este sigur” sau în cea mai tehnică versiune: „…pentru că este bazat pe md5”.
adevărat sau nu, o hashing puternică a parolei este crucială pentru un ecosistem mare precum cel WordPress, care a fost întotdeauna o țintă suculentă pentru hackeri. Așadar, am decis să arunc o privire mai atentă asupra sistemului de hashing și să încerc să sparg hashurile WordPress de la zero!
înțelegerea WordPress parola hashes
am început să fac unele googling și a constatat că cele mai multe informații acolo este generic și confuz. O mulțime de referințe la bibliotecile PHP utilizate (hash portabil de la phpass), dar nimic cu adevărat concret.
am decis să iau o abordare diferită pornind de la o presupunere:
hashing-ul este un proces unidirecțional, dar WordPress este într-un fel capabil să autentifice utilizatorii care își potrivesc introducerea parolei cu hash-ul stocat în baza de date
de acolo, am început să verific codul și am găsit prima funcție interesantă: wp_check_password($password,$hash)
care compară parola text simplu cu hash-ul și returnează true dacă se potrivesc.
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 );
trecând prin cod, ne aduce rapid la CheckPassword
, crypt_private
și encode64
care practic este locul în care se întâmplă magia.
pe scurt, crypt_private($password, $stored_hash)
re-hashes parola înainte de a ajunge în comparație cu hash stocate. Dacă se potrivesc, parola este corectă și autentificarea continuă. Ceea ce înseamnă că putem folosi și această funcție pentru a sparge hash-ul.
anatomie Hash
acesta este un hash WordPress:
1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1
pentru simplitate, vom presupune că site-ul folosește PHP>5 și cel mai nou hash portabil phpass, care este cea mai comună configurare.
primele 3 caractere $P$
sunt un ID, spunând sistemului ce fel de Oh hash avem.
caracterul numărul 3 (numărarea de la 0) este utilizat pentru a determina de câte ori md5() trebuie să proceseze șirul de intrare.
caracterele de la 4 la 12 nPVO4gP9
sunt sarea, care este un șir aleatoriu atașat parolei înainte de hashing, pentru a-i oferi mai multă aleatorie. De exemplu, dacă parola dvs. este admin, aceasta se transformă în nPVO4gP9admin și apoi se hash.
partea rămasă a hash-ului JUMSAM1WlLTHPdH6EDj4e1
este aleatorie reală, generată de parola salt+trecută într-o funcție nedocumentată encode64
, care efectuează unele operații bit pe șirul de intrare și returnează o ieșire de 22 de caractere.
nu e clar, nu? Rămâi cu mine.
până acum știm:
- prima parte a hash-ului este un ID Fix
- al doilea este un singur caracter folosit ca contor, de asemenea fix
- al treilea este sarea, legată de parola
- ultimul este aleatoriu, generat de ‘salt + pass’ procesat de funcția encode64
1
Deci, putem re-scrie logica-sare + parola hash x ori și a trecut în encode64-pentru a efectua un dicționar sau bruteforce atac, și de a obține aceeași ‘ultima parte’ a hash și că ar fi un succes hash crack!
într-un scenariu din viața reală, iar hackerii ar fi mai interesați să găsească parole slabe, deoarece sunt mai susceptibile de a fi reutilizate, în loc de cele aleatorii care sunt adesea generate de un manager de parole și atât de specific site-ului.
rescrierea encode64 folosind golang
am decis să merg cu golang pentru că este foarte rapid, și avem nevoie de toate că viteza pentru a calcula dicționare parola mari.
la fel ca în procedura de criptare WordPress, scriptul ia hash-ul și izolează sarea, apoi compune parola (salt+pass) încercând fiecare parolă din dicționar și md5-hashing X de câte ori și am văzut cum este determinat X.
1itoa64 := "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 2hashloop := 1 << strings.Index(itoa64, string(hash)); // char n. 4 in the hash
făcut că, se efectuează o serie de operații pe biți pe octeți obținute folosind ord () în PHP, care nu avem nevoie în golang ca avem deja valori de octeți:
1itoa64 & 0x3f]
în acest moment, mi-am dat seama că nici măcar nu trebuie să găsim întregul șir. Este suficient să potriviți câteva caractere pentru a se potrivi cu întreaga parolă și pentru a face scriptul mai performant! Deci, datorită naturii procesului de hashing, dacă char n. 0 / 4 / 8 … meciuri, parola a trecut ca intrare este corectă.
și BOOM, am spart hash:
1wphashcrash '$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1' Dev/wphashcrash/dict.txt 2$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1 admin 32020/05/30 12:44:15 Executed in 0.000221
codul este ca de obicei pe GitHub – https://github.com/francescocarlucci/wphashcrash – și în acest moment, scriptul este un POC și primește doar un singur hash de parolă ca intrare și calea către dicționarul de parole.
am subliniat deja în readme câteva îmbunătățiri pe care ar fi frumos să le am și probabil le voi adăuga în viitor.
dacă doriți cu adevărat să încercați să hack o listă de hash-uri, puteți furculiță sau înfășurați doar script-ul într-o bash pentru buclă.
considerații Secuirty
în acest moment, cred că este destul de clar că, dacă un atacator are acces la baza de date de pe un site WordPress, el/ea poate sparge practic fiecare parolă slabă.
acest nefericit, mai ales pentru că:
- injecția SQL nu este atât de rară în pluginurile WordPress
- RCE va acorda, de asemenea, cel mai probabil acces la DB
- ecosistemul WordPress este un teritoriu imens pentru munca freelancerului și este foarte obișnuit să găsești conturi WP-admin și FTP vechi/neutilizate, create pentru nevoi temporare
acest ultim punct, combinat cu enumerarea utilizatorilor care o problemă comună WordPress, lasă ușa deschisă pentru a obține acces la DB folosind acreditările de administrare furate/amanetate.
în plus, multe site-uri web nu aplică parole puternice pentru a nu răni experiența utilizatorului și am experiență directă în oricare dintre punctele menționate.
odată ce un site web este compromis, stocarea hashurilor slabe permite atacatorilor să compromită alte conturi de utilizator de pe alte site-uri, dacă tind să reutilizeze parolele și știm că o fac.
avem soluții?
cercetările mele nu au mers atât de departe, am vrut doar să văd cum să rup hashurile WordPress.
Bcrypt este cunoscut a fi o metodă de hashing mai puternică în comparație cu md5 și există un plugin existent care utilizează bcrypt și înlocuiește toate funcțiile de bază necesare pentru a gestiona parolele:
- wp_check_password ()
- wp_hash_password()
- wp_set_password()
și, desigur, vă puteți scrie propria soluție ca dezvoltator, dar cred că aceasta este o problemă de rezolvat la nivel de bază pentru a viza o adopție mare.
notă finală
există multe instrumente pentru a sparge hash-urile, cum ar fi Hashcat și John The Ripper, care pot fi și mai performante, dar din nou, scopul acestei cercetări este de a înțelege structura hash WordPress și de a o sparge de la zero.
Vă mulțumim pentru lectură.
frenxi