Jak zabezpieczyć logowanie do WordPressa

Jak zabezpieczyć logowanie do WordPressa

Ostatnio zweryfikowano: 13 października 2026
18 min czytania
Przewodnik
Audytor bezpieczeństwa

Większość zgłoszeń typu “WordPress został zhakowany” to nie są ataki zero-day. To credential stuffing na konto admin z hasłem, które wyciekło kilka lat temu z jakiegoś forum, wysyłany na /wp-login.php z rotującej puli proxy. Właściciel strony obwinia WordPressa. Faktyczna przyczyna jest inna: bezpieczeństwo logowania potraktowano jako jeden przełącznik (“silne hasło”) zamiast czterech czy pięciu nakładających się warstw kontroli.

W WordPressie frontowe drzwi znajdują się pod adresem /wp-login.php, a na wielu stronach klucz pod wycieraczką nadal ma napis “admin”. Ten przewodnik przechodzi przez warstwy, które konfiguruję na stronach klientów: higienę nazw użytkowników, 2FA z działającą ścieżką awaryjną w WP-CLI, rate limiting w Cloudflare i na serwerze oraz procedurę na dzień, w którym ktoś zgubi telefon albo wrzuci hasło aplikacji do publicznego repozytorium.

#Najczęstsze ataki na stronę logowania WordPressa

Cztery wzorce pokrywają niemal wszystko, co widać w logach dostępu:

  • Brute force na /wp-login.php: boty wysyłają POST na wp-login.php z parametrami log=admin&pwd=.... Ruch jest rozproszony na setki adresów IP, często z sieci rezydencjalnych proxy. Limit na pojedynczy adres IP ich nie zatrzyma.
  • Credential stuffing: ten sam endpoint, ale dane logowania pochodzą z publicznych zbiorów wycieków (zrzuty “Collection #1” do #5, RockYou2024). Nazwą użytkownika jest login albo e-mail, który wyciekł. Można to uprzedzić, sprawdzając hasło przy jego ustawianiu w API haveibeenpwned.
  • Wzmocnienie przez XML-RPC system.multicall: jeden POST na /xmlrpc.php z treścią system.multicall pozwala sprawdzić setki haseł w jednym żądaniu HTTP, z pominięciem limitów liczonych na żądanie. Jeśli nie używasz aplikacji mobilnej WordPress ani Jetpacka, zablokuj xmlrpc.php na serwerze.
  • Enumeracja użytkowników przez REST API: ?rest_route=/wp/v2/users oraz /wp-json/wp/v2/users zwracają prawdziwe wartości slug dla każdego autora z opublikowanymi wpisami. Ten slug to zwykle login. W połączeniu z wyciekami atakujący ma połowę pary danych logowania.

#Dlaczego login admin to ryzyko dla WordPressa

Dlaczego atakujący lubią nazwę “admin”? Bo skraca ich pracę o połowę. W ataku brute force napastnik musi zgadnąć dwie rzeczy: nazwę użytkownika i hasło. Jeśli używasz “admin”, pierwszą z nich dostaje za darmo. Dlatego usunięcie domyślnych nazw kont to pierwszy krok przy zabezpieczaniu logowania.

#Dlaczego użytkownik z ID 1 to ryzyko

Domyślnie pierwszy użytkownik utworzony w WordPressie ma ID 1. Skanery często odpytują adres twoja-strona.pl/?author=1. Jeśli strona przekieruje je na twoja-strona.pl/author/mariusz/, login (“mariusz”) jest właśnie ujawniony każdemu, kto wie, gdzie szukać.

Ta podatność na enumerację wynika z tego, że WordPress domyślnie tworzy archiwa autorów, które pokazują nazwę użytkownika w adresie URL. Nawet po zmianie nazwy wyświetlanej login często nadal widać w tych archiwach.

#Jak usunąć użytkownika admin bez utraty treści

W WordPressie nie da się po prostu zmienić nazwy użytkownika (loginu). Trzeba przeprowadzić przeszczep, który zachowa całą treść i usunie podatne konto.

  1. Utwórz nowego administratora:
    • Idź do Użytkownicy, Dodaj nowego.
    • Nazwa: coś nieoczywistego (np. Obsydianowy_Orzel_88). Bez imienia i nazwiska, prefiksu e-maila ani niczego, co da się zgadnąć z domeny.
    • E-mail: bezpieczny adres.
    • Rola: Administrator.
    • Hasło: wygenerowane w menedżerze haseł.
  2. Zaloguj się jako nowy administrator: w oknie incognito, żeby mieć pewność, że nie działasz nadal na starej sesji.
  3. Usuń stare konto:
    • Wróć do listy użytkowników.
    • Najedź na “admin” i kliknij Usuń.
    • Krok krytyczny: WordPress zapyta, co zrobić z treścią tego użytkownika.
    • Wybierz “Przypisz całą zawartość do:” i wskaż nowego użytkownika.
    • Dzięki temu wpisy, strony i media zostają przypisane do nowego konta.
  4. Zatwierdź. Konta “admin” już nie ma.

#Jak zablokować enumerację użytkowników w kodzie

Poza usunięciem konta admin warto domknąć dwa źródła wycieku loginów.

Wyłącz archiwa autorów, jeśli ich nie potrzebujesz: regułą serwera (blokada /?author=) albo w functions.php:

// Wyłącza archiwa autorów, żeby nie ujawniać loginów
add_action('template_redirect', function() {
    if (is_author()) {
        wp_redirect(home_url(), 301);
        exit;
    }
});

Zablokuj enumerację przez REST API. Endpoint użytkowników jest domyślnie publiczny dla autorów z opublikowanymi wpisami:

// Usuwa endpointy użytkowników z REST API
add_filter('rest_endpoints', function($endpoints) {
    if (isset($endpoints['/wp/v2/users'])) {
        unset($endpoints['/wp/v2/users']);
    }
    if (isset($endpoints['/wp/v2/users/(?P<id>[\d]+)'])) {
        unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
    }
    return $endpoints;
});

Ten filtr usuwa endpointy dla wszystkich, także dla zalogowanych. Jeśli edytor blokowy lub integracja korzysta z /wp/v2/users, ogranicz blokadę do niezalogowanych żądań i przetestuj panel po zmianie.

#Jak wyłączyć 2FA w WordPressie po utracie dostępu

Samo hasło to pojedynczy punkt awarii. Z 2FA atakujący potrzebuje hasła i drugiego składnika, a przy passkeys (opisanych niżej) w ogóle nie ma wspólnego sekretu, który mógłby wyciec.

Większość poradników pomija scenariusz awarii: administrator gubi telefon, odchodzi z firmy albo sekret TOTP był na urządzeniu, które zostało wyczyszczone. Udokumentowana ścieżka awaryjna w WP-CLI musi istnieć, zanim wymusisz 2FA, a nie po fakcie.

# Awaryjnie: wyłączenie 2FA dla zablokowanego użytkownika (wtyczka Two-Factor; WP 2FA trzyma własne klucze meta)
wp user meta delete <user_id> _two_factor_enabled_providers
wp user meta delete <user_id> _two_factor_provider
wp user meta delete <user_id> _two_factor_totp_key

# Albo najpierw sprawdź, co jest ustawione
wp user meta list <user_id> --keys=_two_factor_enabled_providers,_two_factor_provider

Klucze _two_factor_enabled_providers, _two_factor_provider i _two_factor_totp_key to stałe zdefiniowane w kodzie wtyczki Two-Factor. Komendy uruchamiasz przez SSH na serwerze. Jeśli administrator nie ma już także SSH, zostaje terminal w panelu hostingu albo zapytanie do tabeli wp_usermeta. Bez dostępu do serwera opis wtyczki na WordPress.org wskazuje drogę przez panel: inny administrator edytuje profil zablokowanego użytkownika i odznacza metody w sekcji Two-Factor Options. Zapisz tę procedurę, zanim będzie potrzebna.

#Która metoda 2FA jest najbezpieczniejsza

Metody 2FA nie są równe. Hierarchia pomaga dobrać ochronę do roli konta:

1. Kody SMS (nie używać) 2FA przez SMS było kiedyś powszechne, dziś uchodzi za niebezpieczne. Atak SIM swapping pozwala przejąć numer telefonu, a wiadomości SMS da się przechwycić.

2. Kody e-mail (słabe, ale lepsze niż nic) Jednorazowy kod trafia na adres e-mail konta. To lepsze niż brak 2FA, ale metoda pada razem ze skrzynką pocztową. Tylko gdy nie ma innej opcji.

3. Aplikacje TOTP (standard) Aplikacje Time-based One-Time Password, takie jak Google Authenticator, Authy, Microsoft Authenticator czy Ente Auth, generują kod zmieniany co 30 sekund. Są wyraźnie bezpieczniejsze od SMS i e-maila, bo:

  • kody powstają lokalnie na urządzeniu,
  • sekret nie jest przesyłany przez sieć przy każdym logowaniu,
  • działają offline,
  • opierają się na algorytmie zsynchronizowanym z czasem.

Konfiguracja:

  1. Zainstaluj aplikację TOTP na telefonie.
  2. W WordPressie zeskanuj kod QR wyświetlony przez wtyczkę 2FA.
  3. Wpisz kod weryfikacyjny, żeby potwierdzić konfigurację.
  4. Zapisz kody zapasowe w bezpiecznym miejscu (menedżer haseł).

4. Powiadomienia push (wygodne, ale zależne od dostawcy) Usługi takie jak Duo Security wysyłają powiadomienie do zatwierdzenia na telefonie. To wygodne, ale uzależnia logowanie od infrastruktury dostawcy.

5. Klucze sprzętowe (najmocniejszy standard) Fizyczne klucze, takie jak YubiKey, Titan Security Key i inne urządzenia zgodne z FIDO2, używają kryptografii klucza publicznego:

  • Odporność na phishing: nawet jeśli wpiszesz hasło na fałszywej stronie, uwierzytelnienie się nie uda, bo klucz weryfikuje domenę.
  • Dowód kryptograficzny: protokół challenge-response, którego nie da się odtworzyć.
  • Brak wspólnego sekretu: w odróżnieniu od TOTP na serwerze nie ma sekretu do kradzieży.
  • Wiele protokołów: FIDO2, FIDO U2F i PIV.

#Wtyczki do 2FA w WordPressie

Two-Factor (WordPress.org)

  • Lekka wtyczka publikowana na WordPress.org przez zespół WordPress.org.
  • Według opisu wtyczki obsługuje aplikacje TOTP, kody e-mail i kody zapasowe. Obsługa FIDO U2F została usunięta po wycofaniu jej z przeglądarek.
  • Klucze sprzętowe i passkeys dodaje osobna wtyczka WebAuthn Provider for Two Factor, która integruje się z Two-Factor.
  • Bez płatnych wersji, z hookami dla deweloperów.

WP 2FA (Melapress)

  • Darmowa wersja z obsługą TOTP.
  • Kreator konfiguracji i wymaganie 2FA według ról.

Kadence Security (dawniej Solid Security, wcześniej iThemes Security)

  • Rozbudowany pakiet bezpieczeństwa z 2FA.
  • Obsługuje TOTP, e-mail i kody zapasowe.

Duo Security

  • Rozwiązanie klasy enterprise: push, połączenia telefoniczne i tokeny sprzętowe.
  • Centralne zarządzanie użytkownikami na wielu stronach.

Wybierając wtyczkę, trzymaj się jednej, wąskiej funkcji. Pakiet, który włącza kilkadziesiąt modułów naraz, łatwo zostawić bez właściciela konfiguracji.

#Zasady wdrażania 2FA w WordPressie

  1. 2FA obowiązkowe dla wszystkich administratorów, bez wyjątków.
  2. 2FA dla redaktorów: mogą publikować treść i wpływać na reputację strony.
  3. Kody zapasowe dla każdego: użytkownicy prędzej czy później tracą dostęp do urządzenia.
  4. Okres przejściowy: daj ludziom czas na konfigurację, zanim zaczniesz wymuszać.
  5. Udokumentowana procedura odzyskiwania na wypadek, gdy ktoś sam się zablokuje.

#Jak przeprowadzić audyt haseł aplikacji w WordPressie

Rdzeń WordPressa od wersji 5.6 zawiera hasła aplikacji: 24-znakowe tokeny dla klientów REST API i XML-RPC. Według przewodnika integracji na make.wordpress.org są domyślnie dostępne na stronach serwowanych przez HTTPS. Z założenia omijają 2FA: wtyczka Two-Factor wpuszcza żądania API użytkownika z włączonym 2FA właśnie wtedy, gdy uwierzytelnił się hasłem aplikacji. Takie tokeny trafiają do plików .env w publicznych repozytoriach i do raportów błędów aplikacji wklejanych na fora wsparcia. Przeglądaj je co kwartał:

wp user application-password list <user_id>
wp user application-password delete <user_id> <uuid>

Jeśli nie używasz REST API do uwierzytelnionych zapisów, wyłącz hasła aplikacji całkowicie: add_filter( 'wp_is_application_passwords_available', '__return_false' ); w mu-pluginie.

#Jak passkeys zmieniają logowanie do WordPressa

Passkeys odchodzą od haseł całkowicie. Wykorzystują biometrię urządzenia (Touch ID, Face ID, Windows Hello) do uwierzytelniania kryptografią klucza publicznego.

#Jak działają passkeys

Passkeys korzystają ze standardu WebAuthn i tworzą parę kluczy:

  1. Rejestracja: urządzenie tworzy klucz prywatny (przechowywany lokalnie) i klucz publiczny (wysyłany na serwer).
  2. Uwierzytelnianie: serwer wysyła wyzwanie, urządzenie podpisuje je kluczem prywatnym.
  3. Weryfikacja: serwer sprawdza podpis zapisanym kluczem publicznym.

#Zalety passkeys

  • Brak hasła do kradzieży: nie ma wspólnego sekretu, który mógłby wyciec.
  • Odporność na phishing: klucz prywatny jest powiązany z konkretną domeną.
  • Synchronizacja między urządzeniami: przez Apple ID, konto Google albo menedżer haseł.
  • Wygoda biometrii: odcisk palca lub twarz zamiast wpisywania hasła.

#Wdrożenie passkeys w WordPressie

Wtyczki:

  • Kadence Security: obsługa passkeys dla administratorów.
  • Passkey Login for WordPress: dedykowana implementacja passkeys.
  • Wtyczka Auth0 dla WordPressa: zewnętrzny dostawca tożsamości z obsługą passkeys.

Rozwiązania firmowe: większe organizacje mogą podpiąć dostawcę tożsamości, takiego jak Okta, Microsoft Entra ID (dawniej Azure AD) albo 1Password dla zespołów.

#Jak ograniczyć liczbę prób logowania na wp-login.php i xmlrpc.php

Nawet gdy 2FA blokuje samo przejęcie konta, brute force bez limitów nadal zajmuje procesy PHP-FPM i połączenia MySQL. Na hostingu współdzielonym potrafi położyć stronę bez złamania żadnego hasła. Limity warto mieć na trzech poziomach, w kolejności skuteczności: brzeg sieci (Cloudflare), serwer (Nginx lub Fail2Ban), aplikacja (wtyczka).

#Warstwa 0: rate limiting w Cloudflare

Jeśli strona stoi za Cloudflare, to reguła o największej dźwigni. Plan Free pozwala na jedną regułę rate limiting ze stałym oknem liczenia 10 sekund i blokadą na 10 sekund. Okno 1 minuty i blokada na 1 godzinę z przykładu poniżej wymagają planu Pro, który pozwala też na drugą regułę (dokumentacja Cloudflare). Regułę tworzysz w panelu w sekcji Security, WAF, Rate limiting rules:

  • Pole: URI Path
  • Operator: equals
  • Wartość: /wp-login.php
  • Warunek: 5 żądań na minutę z tego samego IP
  • Akcja: Managed Challenge (albo Block na 1 godzinę)

Drugą regułę dodaj dla /xmlrpc.php, jeśli zostawiasz go włączonego. Przewaga nad Fail2Ban: żądania zatrzymują się na brzegu sieci, zanim dotrą do serwera.

#Warstwa 1: rate limiting we wtyczce

Na hostingu bez dostępu do serwera warstwą aplikacji jest wtyczka. Popularna opcja to Limit Login Attempts Reloaded. Rozsądna konfiguracja:

  • blokada po 3 nieudanych próbach,
  • czas blokady 24 godziny przy powtarzających się porażkach,
  • powiadomienia e-mail o blokadach,
  • biała lista adresów IP biura.

Tam, gdzie masz dostęp do serwera, limity na poziomie Nginx (limit_req) i Fail2Ban działają poza PHP i nie obciążają WordPressa.

#Warstwa 2: CAPTCHA z Cloudflare Turnstile

Google reCAPTCHA bywa irytująca (nikt nie lubi klikać w przejścia dla pieszych), utrudnia dostępność i wysyła dane do Google. Cloudflare Turnstile to nowocześniejsza alternatywa:

  • Niewidoczna: większość użytkowników nie widzi żadnego zadania.
  • Prywatność: nie wymaga śledzenia użytkownika między stronami.
  • Dostępność: działa z czytnikami ekranu.
  • Darmowa: w podstawowym zakresie.

Turnstile sprawdza sygnały z przeglądarki i ocenia, czy odwiedzający jest człowiekiem, bez zmuszania go do układania puzzli.

Wdrożenie:

  1. Załóż darmowe konto Cloudflare.
  2. Przejdź do sekcji Turnstile w panelu.
  3. Utwórz site key i secret key.
  4. Dodaj Turnstile do formularza logowania kodem (skrypt plus site key), przez integrację hostingu albo wtyczką “Simple Cloudflare Turnstile”.
  5. Włącz go na formularzach logowania, rejestracji i resetu hasła.

Widżet ma tryby Managed, Non-interactive i Invisible. Tryb Invisible daje najmniejsze tarcie dla użytkownika.

#Warstwa 3: Fail2Ban na poziomie serwera

Dla użytkowników VPS i serwerów dedykowanych. Fail2Ban czyta logi serwera i automatycznie banuje adresy IP o złośliwym zachowaniu:

  1. Monitoruje pliki logów (np. /var/log/nginx/access.log).
  2. Dopasowuje wzorce z filtrów (np. serię nieudanych logowań).
  3. Aktualizuje reguły firewalla, żeby odciąć dany IP.
  4. Zdejmuje bana po ustalonym czasie albo nigdy.

Atakujący nie dostaje komunikatu o złym haśle, tylko odmowę połączenia.

Instalacja na Ubuntu/Debianie:

sudo apt update
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Konfiguracja pod WordPressa:

Szczegół, który wiele poradników pomija: nieudany POST na wp-login.php zwraca HTTP 200 (strona renderuje się ponownie z błędem), a udany zwraca 302 (przekierowanie do wp-admin). Filtr na POST z kodem 200 liczy więc tylko nieudane próby. Nie odróżni jednak bota od administratora, który trzy razy pomyli hasło w czasie findtime, dlatego adresy biura i VPN wpisz do ignoreip.

Plik /etc/fail2ban/filter.d/wordpress.conf:

[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php.*" 200
            ^<HOST> .* "POST /xmlrpc\.php.*" 200
ignoreregex = ^<HOST> .* "POST /wp-login\.php.*" 302

Plik /etc/fail2ban/jail.local:

[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
backend = auto

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 86400

Backend auto jest tu celowy. Według komentarzy w jail.conf Fail2Ban backend systemd czyta dziennik systemd, a parametr logpath jest dla niego nieprawidłowy, więc jail czytający access log Nginx potrzebuje backendu plikowego.

Rate limiting w Nginx:

# Strefa limitu (w bloku http)
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Limit na wp-login.php
location = /wp-login.php {
    limit_req zone=login burst=5 nodelay;
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}

# Blokada XML-RPC, jeśli nie jest potrzebny
location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

Kontrola Fail2Ban:

sudo fail2ban-client status
sudo fail2ban-client status wordpress
sudo fail2ban-client set wordpress unbanip 192.168.1.1

#Jak monitorować nieudane logowania do WordPressa

Nie zabezpieczysz tego, czego nie widzisz. Monitoring logowań pokazuje wzorce ataków i daje wczesne ostrzeżenie przed przejęciem konta.

#Co monitorować w logach logowania WordPressa

  • Nieudane logowania: według nazwy użytkownika i IP. Wiele różnych loginów z jednego IP to typowy ślad credential stuffingu.
  • Udane logowania: każde logowanie administratora, z godziną i lokalizacją. Alert przy nowej lokalizacji lub urządzeniu.
  • Zmiany kont: zmiany haseł, zmiany ról, nowe konta.
  • Anomalie geograficzne: logowania z nieoczekiwanych krajów i “niemożliwe podróże” (dwa logowania z odległych miejsc w zbyt krótkim czasie).

#Narzędzia do monitoringu logowań na poziomie serwera

  • Logi serwera: /var/log/nginx/access.log (albo Apache) dla żądań na wp-login.php, z rotacją i archiwum na co najmniej 90 dni.
  • Fail2Ban: alerty przy wzorcach brute force.
  • Agregacja logów: Loggly, Splunk lub Datadog dla stron o dużym ruchu lub dużej wartości.
  • Panel hostingu: wielu dostawców pokazuje podsumowania prób logowania.
  • Zewnętrzny monitoring: dostępność i integralność plików.

Alert powinien przyjść natychmiast przy: nieudanych próbach z nowych adresów IP, udanym logowaniu z nietypowego miejsca, zmianie konta administratora, zmianie plików wtyczek, motywów lub rdzenia.

#Jak długo przechowywać i przeglądać logi logowania

Logi bezpieczeństwa trzymaj co najmniej 90 dni, a rok, jeśli wymagają tego przepisy lub umowa. Okres przechowywania ustal razem z wymaganiami RODO, bo adres IP to dane osobowe. Przegląd: co tydzień wzorce nieudanych logowań, co miesiąc trendy blokad, co kwartał ocena całej konfiguracji.

#Co zrobić, gdy WordPress zostanie zhakowany

Mimo zabezpieczeń incydenty się zdarzają. Spisana procedura skraca reakcję.

Faza 1: wykrycie

  • Sygnały: nieoczekiwana aktywność administratorów, nieznane pliki w katalogach WordPressa, nagłe skoki ruchu, ostrzeżenia Google Safe Browsing, zgłoszenia klientów o malware.
  • Zakres: które konta są przejęte, które pliki zmienione, czy baza danych jest naruszona, czy kopie zapasowe są czyste.

Faza 2: powstrzymanie

  • Zmień hasła wszystkich administratorów, wyloguj wszystkich użytkowników (usuń sesje), w razie potrzeby włącz tryb konserwacji, zablokuj podejrzane IP na firewallu.
  • Zabezpiecz dowody: wyeksportuj logi, zanim się zrotują, zachowaj podejrzane pliki, spisz oś czasu.

Faza 3: usunięcie infekcji

  • Wyczyść stronę: pliki rdzenia z oficjalnego źródła, wtyczki ponownie z WordPress.org, tymczasowo domyślny motyw, skan bazy danych pod kątem wstrzykniętego kodu.
  • Zamknij luki: aktualizacje, usunięcie nieużywanych wtyczek i motywów, brakujące zabezpieczenia z tego przewodnika, nowe hasła i klucze API.

Faza 4: odtworzenie

  • Przywróć czystą kopię, jeśli istnieje, sprawdź integralność plików, uruchom stronę ze wzmocnionym monitoringiem i powiadom osoby, których incydent dotyczy (klientów, partnerów, a gdy wymagają tego przepisy, organ nadzorczy).

Faza 5: przegląd po incydencie

  • Ustal wektor ataku, zapisz wnioski, zaktualizuj procedury i przeszkol zespół.

Kontakty na tę okoliczność: zespół bezpieczeństwa hostingu, specjaliści od bezpieczeństwa WordPressa, organy ścigania przy poważnych przestępstwach oraz ubezpieczyciel, jeśli masz polisę cyber.

#Jak zablokować enumerację użytkowników w Apache i Nginx

Skrypty zgadują loginy, skanując /?author=1, /?author=2 i kolejne. Można to zablokować na serwerze.

#Blokada w Apache (.htaccess)

# Blokada skanowania autorów
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (author=\d+) [NC]
RewriteRule .* - [F]
</IfModule>

#Blokada w Nginx

# Blokada enumeracji autorów
if ($args ~* "author=([0-9]*)") {
    return 403;
}

# Blokada enumeracji użytkowników przez REST API
location ~* /wp-json/wp/v2/users {
    deny all;
    return 403;
}

Do samej blokady enumeracji wtyczka nie jest potrzebna, wystarczą powyższe reguły.

#Jak chronić wp-admin listą dozwolonych IP i WAF

#Ograniczenie wp-admin do znanych adresów IP

Jeśli zespół pracuje z kilku stałych adresów IP (biuro, VPN), lista dozwolonych zakresów CIDR na /wp-admin/ usuwa publiczną powierzchnię ataku. Wszystko spoza listy dostaje 403, zanim WordPress się załaduje. Koszt jest realny: administrator w podróży, freelancer w hotelowym wifi i awaryjne logowanie z telefonu przestają działać. Stosuj to tylko z udokumentowanym, stabilnym VPN.

location ^~ /wp-admin/ {
    allow 203.0.113.0/24;     # biuro
    allow 198.51.100.42/32;   # wyjście VPN
    deny all;
    # ...dotychczasowa konfiguracja fastcgi
}
location = /wp-login.php {
    allow 203.0.113.0/24;
    allow 198.51.100.42/32;
    deny all;
}

Na stronach za Cloudflare zrób to regułą WAF: http.request.uri.path matches "^/wp-(admin|login)" oraz not ip.src in {203.0.113.0/24}.

#Czy zmiana adresu wp-login.php poprawia bezpieczeństwo

Przeniesienie adresu logowania to ukrywanie, nie zabezpieczenie. Zmniejsza ruch prostych botów w logach (lepszy stosunek sygnału do szumu), ale zdeterminowany atakujący znajdzie adres w kodzie strony. Traktuj to jako filtr szumu, nigdy jako warstwę ochrony.

#Wyłączenie edycji plików w panelu

Dwie stałe w wp-config.php zamykają najczęstszą ścieżkę eskalacji po przejęciu konta: edycję PHP motywu lub wtyczki z poziomu panelu.

define( 'DISALLOW_FILE_EDIT', true );  // ukrywa edytor plików motywu
define( 'DISALLOW_FILE_MODS', true );  // blokuje też instalację i aktualizacje wtyczek i motywów

DISALLOW_FILE_MODS jest ciężką opcją, bo wyłącza aktualizacje jednym kliknięciem. Stosuj ją tam, gdzie kod trafia na serwer przez CI, a aktualizacje idą przez WP-CLI.

#Web application firewall dla WordPressa

WAF filtruje złośliwy ruch, zanim dotrze do WordPressa:

  • Cloudflare WAF: plan darmowy ma zestaw reguł zarządzanych, plan Pro dodaje OWASP CRS.
  • Sucuri: płatny WAF z wirtualnymi łatkami pod WordPressa.
  • ModSecurity z OWASP CRS: opcja serwerowa dla własnego Nginx lub Apache. Paranoia level 1 to praktyczna baza, wyższe poziomy dają dużo fałszywych alarmów w edytorze Gutenberg.

#SSL/TLS i baza danych

Cała strona, a zwłaszcza logowanie, musi działać po HTTPS: certyfikat (Let’s Encrypt jest darmowy), wymuszone przekierowania na HTTPS, nagłówek HSTS i bezpieczne ciasteczka logowania. Hasła aplikacji i tak wymagają HTTPS. Dla bazy danych: silne hasło użytkownika bazy, dostęp tylko z localhost, regularne i bezpiecznie przechowywane kopie zapasowe.

#Lista kontrolna zabezpieczenia logowania dla stron klientów

To nie ogólna lista dobrych praktyk, tylko kolejność prac przy zabezpieczaniu logowania WordPressa od zera:

  1. Usuń login admin, przypisz treść nowemu kontu, ustaw nickname i display_name ocalałego administratora tak, żeby slug nie zdradzał loginu.
  2. Zablokuj /wp-json/wp/v2/users i ?rest_route=/wp/v2/users dla niezalogowanych żądań filtrem rest_endpoints pokazanym wyżej.
  3. Wymuś 2FA dla ról administrator i editor, z TOTP jako domyślną metodą i procedurą odzyskiwania przez wp user meta delete zapisaną w firmowym menedżerze haseł.
  4. Przejrzyj wp user application-password list dla każdego administratora i usuń hasła starsze niż 90 dni albo nierozpoznane.
  5. Dodaj regułę rate limiting w Cloudflare na /wp-login.php (5 na minutę z Managed Challenge na planie Pro, na Free jedna reguła z oknem 10 sekund) i drugą na /xmlrpc.php, jeśli nie jest zablokowany całkowicie.
  6. Zainstaluj Fail2Ban z filtrem wp-login, który odróżnia 200 (porażka) od 302 (sukces), i wpisz adresy biura do ignoreip.
  7. Ustaw DISALLOW_FILE_EDIT w wp-config.php. DISALLOW_FILE_MODS dodaj tylko wtedy, gdy zespół wdraża przez CI.
  8. Wymuś HTTPS, HSTS z preload oraz flagi Secure; HttpOnly; SameSite=Lax dla ciasteczek wordpress_logged_in_*.
  9. Sprawdź, czy wp-config.php ma unikalne klucze (wp config shuffle-salts), użytkownik bazy ma tylko potrzebne uprawnienia (bez GRANT ALL), a baza przyjmuje połączenia wyłącznie z localhost.

Bezpieczeństwo logowania to cztery lub pięć warstw, nie jedna. Pominięcie jednej nie przekreśla reszty. Pominięcie trzech oznacza powrót do polegania na samym haśle.

Co kwartał sprawdzaj hasła aplikacji, liczbę banów Fail2Ban i procedurę odzyskiwania 2FA. Na przejmowanych stronach zwykle jedno z tych trzech już się rozjechało: stare hasło aplikacji byłego pracownika, Fail2Ban, który od pół roku nikogo nie zbanował, bo zmieniła się ścieżka logu, albo 2FA, którego nikt nie umie obejść, gdy telefon administratora padnie.

Zobacz mój audyt bezpieczeństwa WordPress, jeśli chcesz uporządkować ryzyka i zabezpieczenia serwisu.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Sprawdź inne usługi WordPress i bazę wiedzy

Wzmocnij swój biznes dzięki profesjonalnemu wsparciu technicznemu w kluczowych obszarach ekosystemu WordPress.

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

Czy samo mocne hasło wystarczy do ochrony logowania?#
Nie. Dziś podstawą są 2FA, ograniczenie prób logowania, ukrycie słabych punktów i zabezpieczenia po stronie serwera lub CDN.
Czy warto usuwać użytkownika admin?#
Tak, bo to jedna z najczęściej zgadywanych nazw kont i ułatwia ataki brute force oraz enumerację użytkowników.
Co najlepiej zatrzymuje brute force w WordPressie?#
Połączenie 2FA lub passkeys, rate limiting, Turnstile lub CAPTCHA oraz blokady IP na poziomie serwera, na przykład przez Fail2Ban.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotuję wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły