Bliv en del af mit community / gratis nyhedsbrev — tilmeld dig her
Password-hashing i WordPress 6.8: Den skjulte risiko ved ældre loginintegrationer
Af Greg Nowak. Senest opdateret 2026-07-15.
WordPress 6.8 styrkede lagringen af adgangskoder uden at bede brugerne om at nulstille deres adgangskode. For et almindeligt website, der bruger WordPress' standardlogin, er ændringen bevidst udramatisk. Den driftsmæssige risiko ligger et andet sted: i gamle plugins, medlemsportaler, mobil-API'er, migreringsværktøjer og supportscripts, der behandler felter i WordPress-databasen som en stabil grænseflade til autentificering.
Disse integrationer kan fungere i månedsvis efter en opgradering. Så logger en bruger ind via WordPress, brugerens gamle password-hash bliver erstattet, og en separat loginintegration holder op med at genkende kontoen. Denne forsinkede fejl er grunden til, at ændringen kræver en gennemgang frem for blot en hurtig test af administratorlogin.
Hvad WordPress 6.8 faktisk ændrede
Siden WordPress 6.8 har wp_hash_password() som standard brugt bcrypt. WordPress behandler først adgangskoden med SHA-384 for at undgå bcrypts inputgrænse på 72 byte og gemmer derefter det resulterende hash med et WordPress-specifikt præfiks – normalt $wp$2y$.
Eksisterende phpass-hashes, som normalt kendes på $P$, er fortsat gyldige. I WordPress' almindelige autentificeringsflow med brugernavn og adgangskode kontrollerer systemet efter et vellykket login, om adgangskoden skal hashes igen, og gemmer om nødvendigt et nyt hash. Brugerne migreres ikke i én samlet databaseoperation, så gamle og nye formater kan eksistere side om side på ubestemt tid på et website med brugere, der sjældent logger ind.
WordPress introducerede også wp_fast_hash() til tilfældigt genererede secrets med høj entropi. Applikationsadgangskoder, nøgler til nulstilling af adgangskoder, nøgler til anmodninger om persondata og nøgler til recovery mode kan derfor optræde med præfikset $generic$. Denne hurtige BLAKE2b-baserede mekanisme er ikke beregnet til adgangskoder, som brugerne selv vælger.
Problemet er kontrakten, ikke præfikset
En almindelig rettelse er at lære en integration at håndtere $wp$2y$ og $generic$. Det kan få tjenesten til at fungere igen her og nu, men det fastholder det grundlæggende designproblem: Et internt lagringsformat er blevet en udokumenteret kontrakt mellem systemer.
WordPress ved allerede, hvordan det skal håndtere sit nuværende format, ældre phpass- og MD5-værdier, kompatible hashes oprettet af plugins samt bevidst valgte alternativer som Argon2. Custom code bør kalde det relevante WordPress-API til autentificering i stedet for at genskabe dette beslutningstræ.
| Autentificeringsvej | Advarselstegn | Foretrukken grænseflade | Minimumstest |
|---|---|---|---|
| Browser- eller medlemslogin | Direkte læsning af user_pass |
wp_authenticate() |
Login før og efter genhashing |
| Custom kontrol af adgangskode | Kald til PHP's password_verify() på WordPress-data |
wp_check_password() |
Ældre og aktuelle hashes |
| Applikationsintegration | Inspektion af _application_passwords |
REST-autentificering eller WP_Application_Passwords::check_password() |
Gamle og nyudstedte loginoplysninger |
| Nulstilling af adgangskode | Genimplementering af kontrol af user_activation_key |
check_password_reset_key() |
Forsøg på udstedelse, validering, udløb og genbrug |
| SSO eller socialt login | Fallback-kode tilgår gemte hashes | Udbyderens callback og WordPress' bruger-API'er | Godkendelse, afvisning, logout og fallback |
Søg i kodebasen, før du sporer individuelle fejl
Begynd med custom plugins, must-use-plugins, temakode, deployment-værktøjer og integrationspakker. Disse søgninger er bevidst brede. Et match er en anledning til at undersøge koden, ikke et bevis på en sårbarhed.
rg -n '\$P\$|\$wp\$2y\$|\$generic\$|user_pass|user_activation_key|_application_passwords|PasswordHash' wp-content/
rg -n 'md5\(|password_verify\(|password_hash\(|wp_hash_password|wp_check_password|wp_verify_fast_hash' wp-content/Søg også i repositories uden for WordPress-installationen. En Node-, Java-, .NET- eller ældre PHP-tjeneste, som modtager en kopi af wp_users, er ofte den egentlige årsag til fejlen. Databaseeksporter, rapporteringsreplikaer og migreringskode fortjener også opmærksomhed.
Brug det understøttede API på højest mulige niveau
Ved et almindeligt flow med brugernavn og adgangskode bør WordPress stå for autentificeringsprocessen:
$user = wp_authenticate( $username, $password );
if ( is_wp_error( $user ) ) {
return $user;
}
// Authentication succeeded.Hvis custom code allerede har et brugerobjekt og reelt har brug for at sammenligne en adgangskode, skal du bruge wp_check_password(). Husk, at funktionen kun kontrollerer værdien. Den gemmer ikke selv et nyt hash. Standardflowet wp_authenticate_username_password() udfører genhashingen efter en gyldig kontrol. Et custom flow, der går uden om standardflowet, skal håndtere denne livscyklus eksplicit, herunder de konsekvenser for sessioner, som en opdatering af adgangskoden medfører.
Til applikationsadgangskoder bør du foretrække WordPress' REST-autentificering frem for at læse brugermetadata. Hvis verificering internt i WordPress ikke kan undgås, håndterer WP_Application_Passwords::check_password() både aktuelle hashes og hashes for applikationsadgangskoder fra før 6.8. Brug kun wp_verify_fast_hash() direkte til et egnet secret med høj entropi, som er blevet hashet med den tilsvarende WordPress-mekanisme – ikke som en generisk kontrol af adgangskoder.
Hvis en anden tjeneste skal autentificere WordPress-brugere, er eksport af password-hashes den skrøbelige løsning. Et lille autentificeret endpoint, en etableret identity provider eller en korrekt SSO-grænse holder implementeringen af hashing inde i det system, der ejer den.
En staging-test, der afspejler produktionen
Opbyg en testmatrix omkring brugernes flows, ikke kun omkring funktioner. Medtag en konto med et ældre hash, og bekræft, at det første almindelige login lykkes. Registrer kun hashpræfikset – ikke loginoplysninger eller komplette hashes – og bekræft derefter, at det gemte format ændres, og at endnu et login stadig virker.
Gentag testen via alle reelle indgange: medlemsportal, mobilklient, kundedashboard, supportværktøj til impersonation, SSO-fallback, nulstilling af adgangskode, applikationsadgangskode og recovery-flow. Test både fejlscenarier og succesfulde forløb. En integration, der accepterer en udløbet nulstillingsnøgle eller sender brugbare loginoplysninger til logs, er et mere alvorligt problem end en korrekt afvisning.
Gennemgå til sidst observability. Autentificeringslogs bør identificere route, integration og fejlkategori uden at registrere adgangskoder i klartekst, tokens eller komplette gemte hashes. Det giver driftsteamet tilstrækkelig kontekst til at skelne mellem et proxyproblem, en deaktiveret funktion til applikationsadgangskoder, en afvist SSO-assertion og en inkompatibel ældre loginintegration.
Hvornår en målrettet gennemgang giver mening
Et almindeligt WordPress-website har sandsynligvis ikke brug for et særskilt projekt. Det har et website med custom autentificering, delte brugertabeller, et overtaget medlemsplugin eller loginoplysninger, som kontrolleres af en anden tjeneste, derimod. Det nyttige resultat er et kort over autentificeringsvejene, dokumentation fra staging og en kort liste over nødvendige rettelser – ikke en spekulativ genopbygning.
Hvis det er uklart, hvem der ejer disse flows, kan Greg gennemgå WordPress- og integrationskoden, erstatte direkte håndtering af hashes med understøttede grænseflader og udarbejde en fokuseret testplan til jeres releaseproces. Tal med Greg om en målrettet gennemgang af WordPress-autentificering.
Relateret indhold på GrN.dk
- CodeIgniter-tips og -tricks til sikkert login og nulstilling af adgangskoder
- NGINX 1.30 ændrede standarden for genbrug af upstream-forbindelser: Det skal du kontrollere før opgraderingen
- Når AI skriver JSON, kan ét forkert felt ødelægge hele workflowet
Har du brug for hjælp til denne type opgave?
Spørg Greg om en gennemgang af WordPress-autentificeringen. Kontakt Greg.
Kilder
- WordPress 6.8 vil bruge bcrypt til hashing af adgangskoder
- wp_check_password() – WordPress-ressourcer for udviklere
- wp_authenticate_username_password() – WordPress-ressourcer for udviklere
- wp_verify_fast_hash() – WordPress-ressourcer for udviklere
- WP_Application_Passwords::check_password() – WordPress-ressourcer for udviklere