
🔐 Jaki typ hashu wykorzystuje WordPress
Hasło do panelu administracyjnego, ostatnia rzecz stojąca między hakerem a pełną kontrolą nad stroną. Słabe hasło lub przestarzały mechanizm przechowywania zamieniają drogi hosting i płatny firewall w dekoracje.
W ciągu dwudziestu lat WordPress przeszedł drogę od MD5 do przemysłowego bcrypt. Od wersji 6.8 hashowanie haseł stało się nowoczesne od razu po wyjęciu z pudełka, bez wtyczek i protez. Ale rozumieć, co dokładnie dzieje się z Państwa hasłem po kliknięciu „Zaloguj się", powinien każdy właściciel strony.
Poniżej cały łańcuch: od wprowadzenia hasła w formularzu logowania do ciągu hasha w bazie danych. Z kodem, filtrami i konkretnymi ustawieniami dla tych, którzy chcą więcej, niż daje rdzeń.
💡 Szybki przegląd:
- WordPress 6.8 i nowsze haszują hasła algorytmem bcrypt, tym samym standardem, którego używają banki i systemy rządowe
- Stare hashe (MD5, phpass) są automatycznie aktualizowane do bcrypt podczas następnego logowania użytkownika, migracja jest przezroczysta i nie wymaga ręcznych działań
- Filtr
wp_hash_password_algorithmumożliwia przełączenie na Argon2 jedną linijką kodu, bez wtyczek - Wtyczka PHP Native Password Hash pozostaje działającą opcją dla wersji niższych niż 6.8 i daje precyzyjne dostrojenie parametrów Argon2 przez
wp-config.php
Czym jest hashowanie i dlaczego jest potrzebne WordPressowi
Hashowanie to jednokierunkowe przekształcenie kryptograficzne. Z ciągu o dowolnej długości otrzymują Państwo „odcisk" o stałym rozmiarze. Odwrócenie hasha do pierwotnego hasła jest matematycznie niemożliwe, można jedynie przeglądać warianty i porównywać hashe.

W przeciwieństwie do szyfrowania, gdzie dane odzyskuje się za pomocą klucza, hash to bilet w jedną stronę. Kiedy wprowadzają Państwo hasło podczas logowania, WordPress przepuszcza je przez tę samą funkcję haszującą i porównuje wynik z zapisanym w bazie. Zgodność, dostęp otwarty. Nie, odmowa.
WordPress przechowuje hashe w tabeli wp_users, w polu user_pass. Jeśli baza danych wycieknie, a zdarzało się to nawet gigantom: LinkedIn, Yahoo i Tumblr traciły setki milionów rekordów, atakujący otrzyma nie czytelne hasła, a długie ciągi bcrypt. Odtworzenie hasła z takiego ciągu jest niemożliwe. Ale można je odgadnąć poprzez atak słownikowy, jeśli algorytm jest słaby lub przestarzały. Właśnie dlatego ewolucja hashowania w WordPressie jest tak ważna.
Jak WordPress haszował hasła wcześniej: MD5 i phpass
Przed wersją 2.5 (2008 rok) WordPress używał czystego MD5. Algorytm przekształca hasło o dowolnej długości na 128-bitowy hash z 32 znaków szesnastkowych. Wygląda solidnie, ale MD5 jest podatny na tęczowe tablice, wstępnie obliczone bazy hashów dla miliardów typowych haseł. Haker z dostępem do bazy po prostu szuka hasha w takiej tablicy i natychmiast otrzymuje pierwotne hasło.
Od wersji 2.5 WordPress przeszedł na phpass, przenośną bibliotekę opartą na bcrypt (Blowfish). Dodawała ona do hasła losową „sól" i wielokrotnie przepuszczała wynik przez funkcję haszującą (domyślnie 2^8 = 256 iteracji). Sól czyniła tęczowe tablice bezużytecznymi: dwa identyczne hasła u różnych użytkowników dawały różne hashe. Jednocześnie phpass zachowywał wsteczną kompatybilność z MD5, stare hasła nie psuły się, a podczas logowania były płynnie aktualizowane do nowego formatu.
To wystarczało przez długie lata. Ale branża poszła naprzód: nowoczesny sprzęt, farmy GPU i ASIC przeglądają miliardy hashów na sekundę. Algorytm bcrypt z konfigurowalnym kosztem iteracji (cost factor) stał się standardem przemysłowym. I począwszy od WordPressa 6.8 rdzeń używa go natywnie.
WordPress 6.8 i bcrypt: co się zmieniło
Wydanie WordPress 6.8 „Cecil" (kwiecień 2025) przyniosło pełne przejście na bcrypt. Wcześniej rdzeń używał własnej klasy PasswordHash z biblioteki phpass, teraz wywoływana jest natywna funkcja PHP password_hash() ze stałą PASSWORD_BCRYPT.

Główne zmiany w funkcji wp_hash_password():
- bcrypt domyślnie. Wszystkie nowe hasła są haszowane przez
password_hash()z algorytmem bcrypt i cost factor zadanym przez serwer PHP (zazwyczaj 10). - Automigracja starych haseł. Podczas logowania użytkownika WordPress sprawdza przez
password_needs_rehash(), czy nie czas zaktualizować hash. Stary format phpass ($P$...) jest przezroczyście zastępowany przez bcrypt. - Ochrona długich haseł. bcrypt obcina hasła dłuższe niż 72 bajty, zmniejszając entropię. WordPress 6.8 rozwiązuje to przez wstępne hashowanie przez SHA-384 z kluczem domenowym
wp-sha384i kodowaniem w base64. Hasło o długości 100 znaków zachowuje pełną odporność. - Filtry do elastycznej konfiguracji. Pojawiły się hooki
wp_hash_password_algorithm(wybór algorytmu) orazwp_hash_password_options(parametry: cost, memory_cost, threads).
Wywołanie wp_hash_password() w rdzeniu WordPress 6.8 wygląda następująco:
1 function wp_hash_password( $password ) { 2 global $wp_hasher; 3 4 if ( ! empty( $wp_hasher ) ) { 5 return $wp_hasher->HashPassword( trim( $password ) ); 6 } 7 8 if ( strlen( $password ) > 4096 ) { 9 return '*'; 10 } 11 12 $algorithm = apply_filters( 'wp_hash_password_algorithm', PASSWORD_BCRYPT ); 13 $options = apply_filters( 'wp_hash_password_options', array(), $algorithm ); 14 15 if ( PASSWORD_BCRYPT !== $algorithm ) { 16 return password_hash( $password, $algorithm, $options ); 17 } 18 19 $password_to_hash = base64_encode( 20 hash_hmac( 'sha384', trim( $password ), 'wp-sha384', true ) 21 ); 22 23 return '$wp' . password_hash( $password_to_hash, $algorithm, $options ); 24 }
Funkcja najpierw sprawdza, czy logika hashowania nie została nadpisana przez zewnętrzną wtyczkę (zmienna globalna $wp_hasher). Następnie odcina hasła dłuższe niż 4096 znaków, takie próby logowania zwracają *, co uniemożliwia uwierzytelnienie. Dalej, najciekawsze: filtr wp_hash_password_algorithm określa algorytm. Jeśli wybrano NIE bcrypt, hasło jest haszowane bezpośrednio. Jeśli bcrypt, hasło najpierw przechodzi przez SHA-384 z kluczem wp-sha384, jest kodowane w base64 i dopiero potem przekazywane do password_hash(). Na wyjściu hash z prefiksem $wp, który odróżnia „wordpressowy" bcrypt od waniliowego. Przydatne podczas audytu bazy lub integracji z systemami zewnętrznymi.
Jak wzmocnić hashowanie do Argon2
bcrypt to doskonały poziom podstawowy. Następny krok, Argon2, zwycięzca konkursu Password Hashing Competition z 2015 roku. Argon2 został specjalnie zaprojektowany do przeciwdziałania atakom GPU: jest wymagający pamięciowo, a karty graficzne są tu wąskim gardłem.

Wariant 1: hook wp_hash_password_algorithm (WordPress 6.8+)
Proszę dodać w functions.php motywu potomnego lub przez wtyczkę Code Snippets:
1 add_filter( 'wp_hash_password_algorithm', function() { 2 return PASSWORD_ARGON2ID; 3 });
Kilka sekund i WordPress przechodzi na Argon2ID. Stare hasła są automatycznie ponownie haszowane podczas logowania użytkowników. Hosting musi obsługiwać Argon2 w PHP, wymagana jest wersja 7.3 lub nowsza dla Argon2ID. Dostępność można sprawdzić wywołaniem password_algos().
Do precyzyjnego dostrojenia parametrów proszę użyć sparowanego hooka:
1 add_filter( 'wp_hash_password_options', function( $options, $algorithm ) { 2 if ( PASSWORD_ARGON2ID === $algorithm ) { 3 return array( 4 'memory_cost' => 65536, // 64 MB 5 'time_cost' => 4, 6 'threads' => 2, 7 ); 8 } 9 return $options; 10 }, 10, 2 );
Parametr memory_cost określa, ile pamięci algorytm musi wykorzystać podczas obliczania hasha: im więcej, tym trudniejsze przeglądanie na GPU. time_cost określa liczbę iteracji, a threads liczbę wątków.
Wariant 2: wtyczka PHP Native Password Hash
Dla wersji WordPressa nowszych niż 6.8 wtyczka PHP Native Password Hash robi to samo. Podmienia całą logikę haszowania na natywną funkcję password_hash(), obsługuje bcrypt i Argon2 oraz nie ma interfejsu, wszystkie ustawienia realizuje się przez stałe w pliku wp-config.php:
1 define( 'WP_PASSWORD_HASH_ALGO', PASSWORD_ARGON2ID ); 2 define( 'WP_PASSWORD_HASH_OPTIONS', [ 3 'memory_cost' => 65536, 4 'time_cost' => 4, 5 'threads' => 2, 6 ] );
Wtyczka nie była aktualizowana od ponad dwóch lat, ale jej kod jest minimalny i stabilny. Od WordPressa 6.8 jej funkcjonalność wbudowano w rdzeń, można ją usunąć i korzystać z natywnych filtrów.
Generatory haszy: co działa dzisiaj
Zdarzają się sytuacje, gdy hash trzeba wygenerować ręcznie: bezpośrednio wpisać hasło do bazy przez phpMyAdmin lub przenieść użytkowników z systemu zewnętrznego.

Generator online z passwordtool.hu, popularny w czasach starych wersji WordPressa, nie jest już dostępny: witryna zmieniła właściciela. Działające dziś alternatywy:
- WP-CLI: polecenie
wp user update <id> --user_pass="новыйпароль"zrobi wszystko poprawnie przezwp_hash_password(). Szybko, bezpiecznie i z gwarancją poprawności. - Skrypt PHP w katalogu głównym witryny: tymczasowo proszę utworzyć plik z wywołaniem
echo wp_hash_password('пароль');i usunąć go natychmiast po użyciu. - Dowolny generator bcrypt online: na przykład bcrypt.online. Proszę jednak pamiętać: WordPress 6.8 dodaje prefiks
$wpi wstępne haszowanie SHA-384, więc zwykły hash bcrypt nie nadaje się do bezpośredniego wstawienia do bazy.
W praktyce najpewniejsze jest WP-CLI.
Jak wybrać hasło, którego nie złamią
Nawet bcrypt nie pomoże, jeśli hasłem jest admin123. Hakerzy rozpoczynają atak właśnie od ataku słownikowego.

Narzędzie zxcvbn od Dropbox, wbudowane w WordPress do oceny haseł w panelu administracyjnym, odrzuca popularne wzorce: daty urodzenia, 123456 i qwerty, imiona zwierząt domowych. Analizuje ono hasło pod kątem słowników, układów klawiatury i wzorców zastępowania znaków. Ocena „słabe" oznacza, że hasło zostanie odgadnięte w ciągu sekund.
Trzy praktyczne zasady:
- Losowe słowa, a nie mieszanka znaków. Hasło złożone z czterech-pięciu niepowiązanych ze sobą angielskich słów z separatorami (np.
correct-horse-battery-staple) zapamiętuje się łatwiej niżTr0ub4dor&3, a jego złamanie trwa wielokrotnie dłużej. - Długość jest ważniejsza niż złożoność. Szesnaście losowych małych liter daje większą entropię niż 8 znaków ze znakami specjalnymi. Natomiast bcrypt w WordPress 6.8, dzięki wstępnemu haszowaniu SHA-384, zachowuje entropię haseł o dowolnej rozsądnej długości.
- Menedżer haseł. Ludzka pamięć to słabe narzędzie do zapamiętania kilkunastu unikalnych haseł. 1Password, płatny standard z planem rodzinnym, KeePass, darmowy open source z lokalną bazą danych, Bitwarden, złoty środek: darmowy, w chmurze, otwarty kod źródłowy.

Menedżer generuje, przechowuje i automatycznie wypełnia hasła. Panu/Pani pozostaje zapamiętanie tylko jednego hasła głównego. A jeśli serwis obsługuje uwierzytelnianie dwuskładnikowe, proszę je koniecznie włączyć. Hasło plus jednorazowy kod z aplikacji sprawiają, że logowanie staje się praktycznie nie do przełamania.
Wideo: jak działa haszowanie haseł w WordPress
Krótkie wyjaśnienie mechanizmu haszowania, od wpisania hasła do zapisania go w bazie danych WordPress:
⁉️🤔 Często zadawane pytania
Hasła haszowane starym MD5 nadal działają w WordPress 6.8+?
Tak. Podczas logowania użytkownika WordPress widzi stary format hasha, weryfikuje hasło za pomocą poprzedniego algorytmu i, jeśli wszystko się zgadza, przezroczyście aktualizuje hash do bcrypt. Nie ma potrzeby usuwać starych użytkowników ani wymuszać resetowania haseł.
Czy w WordPress 6.8 i nowszych potrzebna jest wtyczka PHP Native Password Hash?
Nie. Wszystko, co robiła wtyczka, czyli haszowanie przez
password_hash()i obsługa Argon2, jest teraz dostępne przez natywne filtrywp_hash_password_algorithmiwp_hash_password_options. Wtyczka pozostaje aktualna tylko dla wersji starszych niż 6.8.
Czy można wrócić z Argon2 z powrotem do bcrypt?
Technicznie tak, zmieniając algorytm w filtrze. Jednak stare hashe Argon2 nie zostaną rozpoznane i użytkownicy będą musieli zresetować hasła. Jeśli eksperymentuje Pan/Pani z algorytmem na działającej stronie, proszę najpierw wykonać pełną kopię zapasową bazy danych.
Czy bcrypt pomaga w przypadku wycieku bazy danych?
bcrypt sprawia, że łamanie haseł na podstawie wyciekłych hashy jest setki tysięcy razy wolniejsze niż w przypadku MD5. Przy cost factor 10 złamanie jednego hasha na nowoczesnym CPU zajmuje około 0,1 sekundy, więc miliard wariantów zająłby lata. Jeśli jednak hasłem jest
password, zostanie ono znalezione w pierwszej iteracji ataku słownikowego. Algorytm chroni złożone hasła; słabych nie uratuje nic.
Jak sprawdzić, czy moje hasła są haszowane bcrypt?
Proszę zajrzeć do tabeli
wp_usersprzez phpMyAdmin. Poleuser_passu nowych użytkowników (oraz tych, którzy zalogowali się po aktualizacji do 6.8) powinno zaczynać się od prefiksu$wp(oznaka nowego formatu bcrypt WordPress). Stare hashe phpass mają postać$P$B.... W celu masowego sprawdzenia proszę wykonać zapytanie SQL:SELECT COUNT(*) FROM wp_users WHERE user_pass NOT LIKE '$wp$%' AND user_pass NOT LIKE '$P$%';, pokaże ono, ile haseł utknęło w przestarzałym formacie, jeśli takie istnieją.
Co zrobić z haszowaniem WordPress już teraz
Jeśli Pana/Pani strona na WordPress jest w wersji 6.8 lub nowszej, korzysta Pan/Pani już z bcrypt i nie trzeba nic robić. Rdzeń samodzielnie aktualizuje stare hashe podczas logowania użytkowników, migracja jest całkowicie przezroczysta.
Jeśli chce Pan/Pani Argon2, proszę dodać filtr wp_hash_password_algorithm z PASSWORD_ARGON2ID w pliku functions.php. Wcześniej proszę upewnić się, że hosting obsługuje Argon2: proszę wykonać var_dump(password_algos()); przez skrypt testowy. Na większości nowoczesnych hostingów wsparcie jest dostępne.
W wersji starszej niż 6.8 proszę zainstalować wtyczkę PHP Native Password Hash, która zapewni bcrypt lub Argon2 bez aktualizacji rdzenia. A przy okazji proszę zaplanować aktualizację WordPress: każda duża aktualizacja zamyka dziesiątki luk w zabezpieczeniach, nie tylko w haszowaniu.
I co najważniejsze, proszę zmienić admin123 na coś przyzwoitego. Żaden algorytm nie uratuje przed atakiem słownikowym, jeśli hasło znajduje się w pierwszej setce listy rockyou.txt.



