hvis Du liker Å Gå Til WordCamps som jeg gjør, har du sikkert hørt dette allerede: «WordPress passord hashing er ikke trygt», eller i den mest tekniske versjonen:»…fordi det er md5 basert».
Sant eller ikke, et sterkt passord hashing er avgjørende for et stort økosystem som WordPress, som alltid har vært et saftig mål for hackere. Så bestemte jeg meg for å se nærmere på hashingsystemet og prøve Å knekke WordPress hashes fra bunnen av!
Forstå WordPress passord hashes
jeg begynte å gjøre litt googling og fant ut at det meste av informasjonen der ute er generisk og forvirrende. Mange referanser TIL PHP-bibliotekene som brukes (portable hash fra phpass), men ingenting virkelig konkret.
jeg bestemte meg for å ta en annen tilnærming fra en antagelse:
hashing er en enveis prosess, Men WordPress er someway i stand til å autentisere brukere som samsvarer med passordinngangen med hash lagret i databasen
Derfra begynte jeg å sjekke koden og fant den første interessante funksjonen: wp_check_password($password,$hash)
som sammenligner ren tekstpassordet med hash og returnerer sant hvis de samsvarer.
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 );
Å gå gjennom koden, bringer oss raskt til CheckPassword
, crypt_private
og encode64
som i utgangspunktet er hvor magien skjer.
Lang historie kort, crypt_private($password, $stored_hash)
re-hashes passordet før det blir sammenlignet med den lagrede hash. Hvis de samsvarer, er passordet riktig og autentiseringen fortsetter. Det betyr at vi også kan bruke den funksjonen til å knekke hash.
Hash anatomi
Dette Er En WordPress hash:
1$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1
for enkelhets skyld antar vi at nettstedet bruker PHP>5 og den nyeste phpass portable hash, som er det vanligste oppsettet.
de første 3 tegnene $P$
er EN ID som forteller systemet hvilken type oh hash vi har.
Tegn nummer 3 (teller fra 0) brukes til å bestemme hvor mange ganger md5 () må behandle inngangsstrengen.
Tegn fra 4 til 12 nPVO4gP9
er saltet, som er en tilfeldig streng lagt til passordet før hashing, for å gi det mer tilfeldighet. For eksempel, hvis passordet ditt er admin, blir det vendt til nPVO4gP9admin og deretter hashed.
den gjenværende delen av hash JUMSAM1WlLTHPdH6EDj4e1
er den virkelige tilfeldigheten, generert av salt + passordet som sendes i en udokumentert encode64
– funksjon ,som utfører noen bitvis operasjoner på inngangsstrengen og returnerer en 22 tegn utgang.
Ikke så klart, uh? Hold deg til meg.
Så langt vet vi:
- den første delen av hash er en fast id
- den andre er en enkelt char brukt som teller, også fast
- den tredje er saltet, knyttet til passordet
- den siste er tilfeldig, generert av ‘salt + pass’ behandlet av encode64-funksjonen
1
Så, vi kan omskrive logikken-salt + passord hashed X ganger Og bestått i kode64 – for å utføre en ordbok eller bruteforce angrep, og få den samme ‘siste delen’ av hash og det ville være en vellykket hash sprekk!
i en real-life scenario, og hackere ville være mer interessert i å finne svake passord fordi de er mer sannsynlig å bli gjenbrukt, i stedet for tilfeldige de som ofte genereres av en passord manager og så stedsspesifikke.
Skrive kode64 bruker golang
jeg bestemte meg for å gå med golang fordi det er veldig fort, og vi trenger all den hastigheten til å beregne store passord ordbøker.
akkurat som I wordpress krypteringsprosedyren, tar skriptet hash og isolerer saltet, så komponerer det passordet (salt+pass) som forsøker hvert passord I ordboken Og md5-hashing x antall ganger, og vi har sett Hvordan X er bestemt.
1itoa64 := "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 2hashloop := 1 << strings.Index(itoa64, string(hash)); // char n. 4 in the hash
Gjort det, det utfører en serie bitvis operasjon på byte oppnådd ved hjelp av ord () I PHP, som vi ikke trenger i golang som vi allerede har byte-verdier:
1itoa64 & 0x3f]
På dette punktet innså jeg at vi ikke engang trenger å finne hele strengen. Det er nok å matche noen få tegn for å matche hele passordet og gjøre skriptet mer effektivt! Så, på grunn av arten av hashing prosessen, hvis char n. 0 / 4 / 8 … matcher, passordet bestått som inngang er riktig.
OG BOOM, vi sprakk hasj:
1wphashcrash '$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1' Dev/wphashcrash/dict.txt 2$P$BnPVO4gP9JUMSAM1WlLTHPdH6EDj4e1 admin 32020/05/30 12:44:15 Executed in 0.000221
koden er som vanlig På GitHub – https://github.com/francescocarlucci/wphashcrash – og for øyeblikket er skriptet EN POC og får bare et enkelt passord hash som inngang, og banen til passordordlisten.
jeg har allerede skissert i readme noen forbedringer som ville være fint å ha, og jeg vil nok legge til i fremtiden.
Hvis du virkelig vil prøve å hacke en liste over hashes, kan du gaffel den eller bare pakke skriptet i en bash for loop.
Sikkerhetsmessige hensyn
På dette punktet tror jeg det er klart nok at hvis en angriper får tilgang til databasen På Et WordPress-nettsted, kan han/hun i utgangspunktet knekke hvert svakt passord.
dette uheldig, spesielt fordi:
- SQL Injection er ikke så sjelden I WordPress plugins
- RCE vil også mest sannsynlig gi tilgang TIL DB
- WordPress økosystem Er et stort territorium for freelancer arbeid og er svært vanlig å finne gamle/ubrukte wp-admin og FTP kontoer, opprettet for midlertidige behov
dette siste punktet, kombinert med brukeropptelling som Et WordPress-vanlig problem, forlater døren åpen for å få tilgang til db ved hjelp av stjålet/pantsatt admin legitimasjon.
på toppen av dette håndhever mange nettsteder ikke sterke passord for ikke å skade brukeropplevelsen, og jeg har direkte erfaring i noen av de nevnte punktene.
når et nettsted er kompromittert, har svake hashes lagret angripere å kompromittere andre brukerkontoer på andre nettsteder, hvis de har en tendens til å gjenbruke passord, og vi vet at de gjør det.
har vi løsninger?
min forskning gikk ikke så langt, jeg ville bare se hvordan å bryte WordPress hashes.
Bcrypt er kjent for å være en sterkere hashing metode i forhold til md5, og det er en eksisterende plugin som bruker bcrypt og erstatter alle kjernefunksjoner som trengs for å håndtere passord:
- wp_check_password()
- wp_hash_password ()
- wp_set_password()
Og selvfølgelig kan du skrive din egen løsning som utvikler, men jeg tror dette er et problem å fikse på kjernenivå for å sikte på en stor adopsjon.
Endelig notat
Det er mange verktøy for å knekke hasher, som Hashcat Og John The Ripper som kan være enda mer performant, men igjen er omfanget av denne undersøkelsen å forstå WordPress hash-strukturen og knekke den fra bunnen av.
Takk for at du leste.
frenxi