Kto przeprowadza audyt?
Ja, Mariusz Szatkowski. Jestem developerem WordPressa z Gdyni i pracuję z nim od 2006 roku. Audyt robię sam, bez zespołu i podwykonawców, więc dostępy do Twojej strony nie trafiają do nikogo innego.
Co sprawdzam w audycie?
Audyt to pisemny przegląd strony. Sprawdzam:
- wtyczki i motyw: wersje, znane podatności w bazach WPScan i Patchstack, porzucone projekty, kod własnych wtyczek,
- konta i role: kto ma uprawnienia administratora, hasła aplikacji, logowanie dwuskładnikowe,
- konfigurację:
wp-config.php, uprawnienia plików, PHP w katalogu uploads, XML-RPC, publiczne endpointy REST, - nagłówki serwera: HTTPS, HSTS, Content-Security-Policy i to, co serwer zdradza o swoich wersjach,
- kopie zapasowe: gdzie leżą, jak długo są trzymane i czy da się z nich odtworzyć stronę,
- integralność plików: sumy kontrolne rdzenia i wtyczek względem wersji z WordPress.org.
Wynikiem jest dokument z poprawkami ułożonymi według priorytetu. Usuwanie wirusów po włamaniu to osobne zlecenie.
Czym jest audyt bezpieczeństwa WordPress
Audyt odpowiada na jedno pytanie: którędy dziś da się wejść na Twoją stronę i co z tym zrobić w pierwszej kolejności. Nie jest testem penetracyjnym ani stałym monitoringiem. Czytam konfigurację, kod i ustawienia, porównuję wersje z bazami podatności i opisuję, co znalazłem.
Ryzyko siedzi głównie we wtyczkach. Według raportu Patchstack w 2024 roku w ekosystemie WordPressa zgłoszono 7966 nowych podatności, 96% z nich we wtyczkach, a w samym rdzeniu siedem. Dlatego większą część audytu spędzam na wtyczkach, a nie na rdzeniu.
Jeśli potrzebujesz kogoś, kto po audycie wdroży konkretne poprawki w kodzie, opisuję to na stronie specjalista WordPress.
Jak dochodzi do włamań na strony WordPress
Włamania, które oglądam po fakcie, powtarzają się według kilku wzorców. Znając je, wiesz, czego szukać w kodzie i w logach.
Podatności we wtyczkach WordPress
Rdzeń WordPressa jest dziś dobrze utwardzony, więc atak idzie zwykle przez wtyczkę:
- endpoint REST zarejestrowany z
permission_callback => '__return_true', czyli dostępny dla każdego, - XSS w shortcode’ach, które wypisują
$_GETalbo post meta bezwp_kses_post()czyesc_html(), - upload przez AJAX bez
wp_check_filetype_and_ext()i listy dozwolonych typów MIME, po którym w/wp-content/uploads/ląduje plik PHP, - zmiana ról użytkowników przez formularz ustawień, który ufa danym z żądania i nie sprawdza
current_user_can().
W audycie porównuję zainstalowane wtyczki z bazami WPScan i Patchstack, a kod wtyczek mniej znanych i pisanych na zamówienie czytam pod kątem tych wzorców. Sama baza CVE nie wystarcza, bo luki, której nikt jeszcze nie zgłosił, w niej nie ma.
Enumeracja użytkowników WordPress
?author=1 przekierowuje na /author/<slug>/ i zdradza login. Podobnie /wp-json/wp/v2/users na instalacjach, które nie ograniczyły publicznego endpointu użytkowników. Po zabezpieczeniu oba adresy powinny zwracać 404 albo pustą listę.
XML-RPC
/xmlrpc.php to częsty cel botów zgadujących hasła. Metoda system.multicall pozwala w jednym żądaniu sprawdzić setki haseł. Jeśli nie korzystasz z Jetpacka ani aplikacji mobilnej WordPress, można go wyłączyć. Jeśli korzystasz, lepiej ograniczyć dostęp na poziomie WAF, na przykład regułą Cloudflare z wyzwaniem dla /xmlrpc.php.
Audyt stron WordPress zbudowanych przez AI
Strony tworzone albo rozbudowywane narzędziami AI wypadają w audycie słabo z przewidywalnych powodów. Wygenerowany PHP często nie ma wp_verify_nonce(), przy akcjach w panelu brakuje current_user_can(), a $_POST trafia na stronę bez oczyszczenia. Kolejne prompty dokładają kolejne wtyczki, w tym kilka wtyczek bezpieczeństwa naraz, które sobie przeszkadzają.
| Warstwa | Co sprawdzam | Typowe znalezisko |
|---|---|---|
| Kod | własne wtyczki, functions.php motywu, mu-plugins | brak nonce, nieoczyszczone dane wejściowe, SQL sklejany z tekstu |
| Powierzchnia | trasy REST, akcje AJAX, upload plików | permission_callback => '__return_true', otwarty upload |
| Treść | zduplikowane strony, zmyślone statystyki i cytaty | treść, która podkopuje zaufanie do firmy |
Naprawę takich stron opisuję na stronie naprawa stron zrobionych przez AI, wzorce w kodzie w tekście o audycie kodu wtyczek generowanych przez AI, a treść w czyszczeniu treści AI-slop.
Czy wtyczki AI z wykonaniem kodu są bezpieczne
Zwykły audyt szuka podatności: starych wersji, znanych CVE, złej walidacji. Coraz częściej trafiam na inny rodzaj ryzyka: wtyczki, które celowo dają agentowi AI wykonanie PHP, zapytania do bazy i operacje na plikach (przez MCP, CLI albo webhook). To działa zgodnie z opisem wtyczki, a w praktyce oznacza zdalne wykonanie kodu przez kogoś z zewnątrz.
Skaner CVE uzna taką wtyczkę za czystą, bo nie ma w niej błędu do zgłoszenia. Ryzyko przenosi się na uwierzytelnienie i łańcuch dostaw: kto ma klucz do endpointu, gdzie leży sekret, czy endpoint jest publiczny i co się stanie po przejęciu konta u dostawcy modelu.
W audycie sprawdzam przy tym pięć rzeczy:
- Które wtyczki deklarują wykonanie kodu, dostęp do bazy albo do plików przez agenta AI.
- Czy ich endpointy wymagają uwierzytelnienia i czy są dostępne z internetu.
- Gdzie leżą poświadczenia (
wp-config.php, opcje w bazie, zmienne środowiskowe) i kto ma do nich dostęp. - Czy jest log wykonanych operacji, z którego da się coś odtworzyć po incydencie.
- Domyślnie zalecam: na produkcji nie, na stagingu tylko świadomie i z ograniczeniem po IP.
W raporcie traktuję to na równi z backdoorem w uploadach, bo skutek jest podobny: ktoś z zewnątrz może zmieniać pliki i dane.
Checklista audytu bezpieczeństwa WordPress
Audyt przechodzi zawsze te same etapy. Kolejność wynika z tego, co da się sprawdzić bez dostępu, a co wymaga zalogowania.
| Etap | Co robię | Narzędzia |
|---|---|---|
| 1. Widok z zewnątrz | Nagłówki HTTP, wersje widoczne publicznie, czarne listy (Google Safe Browsing), publiczne endpointy | curl, WPScan, Sucuri SiteCheck |
| 2. Pliki rdzenia i wtyczek | Porównanie sum kontrolnych z wersjami z WordPress.org, pliki PHP w uploads | WP-CLI |
| 3. Wtyczki i motyw | Znane podatności, porzucone projekty, przegląd kodu własnego | bazy WPScan i Patchstack |
| 4. Konta i role | Administratorzy, hasła aplikacji, logowanie dwuskładnikowe | WP-CLI, panel |
| 5. Baza danych | Wstrzyknięte skrypty i linki, konta dopisane poza panelem | zapytania SQL |
| 6. Kopie zapasowe | Miejsce przechowywania, okres przechowywania, próba odtworzenia | panel hostingu, kopia testowa |
| 7. Logi serwera | access.log i error.log, ślady prób logowania i uploadu | SSH, grep |
Najczęstsze rodzaje infekcji (malware)
Pharma hack i japoński spam SEO
Atakujący dopisuje tysiące podstron z japońskimi albo chińskimi znakami, które reklamują podróbki. W wynikach Google pod Twoją domeną pojawiają się obce tytuły, a widoczność strony spada.
Złośliwe przekierowania
Gość trafia na strony hazardowe albo pornograficzne. Często tylko z telefonu albo z wybranych krajów, więc właściciel tego nie widzi. Zwykle odpowiada za to zmieniony header.php, wpis w .htaccess albo skrypt wstrzyknięty do bazy.
Backdoory PHP
Ukryte skrypty, na przykład udające pliki systemowe w wp-includes, które pozwalają wrócić na stronę nawet po zmianie haseł.
Jak zrobić hardening WordPressa
Hardening to zestaw ograniczeń, które utrudniają kolejne ataki. W raporcie układam zalecenia mniej więcej w tej kolejności.
Stałe w wp-config.php. DISALLOW_FILE_EDIT wyłącza edytor plików w panelu. DISALLOW_FILE_MODS blokuje dodatkowo instalację i aktualizację wtyczek z panelu, więc ma sens tylko wtedy, gdy aktualizacje idą przez wdrożenie. FORCE_SSL_ADMIN wymusza HTTPS w panelu. Sam plik powinien mieć uprawnienia 440 albo 400 i należeć do użytkownika wdrożenia, a nie do serwera WWW. Klucze API (KSeF, Przelewy24, Tpay) lepiej trzymać w zmiennych środowiskowych poza katalogiem strony.
Sekrety. Po każdym podejrzeniu włamania zalecam wymianę ośmiu kluczy i soli (AUTH_KEY, SECURE_AUTH_KEY i pozostałych) z generatora WordPress.org, co wylogowuje wszystkie sesje. Przeglądam też hasła aplikacji w profilach użytkowników i wskazuję te, których nikt nie umie przypisać do integracji.
Logowanie. Two Factor albo Wordfence Login Security z kodami TOTP, do tego opisany sposób odzyskania dostępu przez WP-CLI, gdy ktoś zgubi telefon. Ograniczenie prób logowania najlepiej działa przed PHP, na przykład regułą Cloudflare dla żądań POST do /wp-login.php.
System plików. PHP wyłączone w /wp-content/uploads/ regułą <FilesMatch "\.php$"> Require all denied </FilesMatch> w .htaccess albo odpowiednim blokiem location w nginx. Wyłączone listowanie katalogów. xmlrpc.php zablokowany, jeśli strona go nie potrzebuje.
Filtrowanie na brzegu. Jeśli hosting ma ModSecurity z regułami OWASP CRS, lepiej opisać wyjątki dla konkretnej strony niż wyłączać całość. Przy Cloudflare i danych osobowych sprawdź, czy masz zawartą umowę powierzenia z dostawcą.
Wykrywanie, nie tylko zapobieganie. Regularne porównanie sum kontrolnych rdzenia i wtyczek (wp core verify-checksums, wp plugin verify-checksums --all), powiadomienie o każdym nowym koncie administratora i fail2ban czytający log dostępu pod kątem prób logowania. Taki zapis przydaje się później jako dokumentacja naruszenia, której art. 33 ust. 5 RODO wymaga od administratora.
Najczęstsze incydenty po włamaniu na WordPress
Ukryty administrator. Dziurawa wtyczka formularzy pozwala wywołać wp_insert_user() przez źle zabezpieczoną akcję AJAX. Konto dostaje rolę administratora i niewinną nazwę w rodzaju „Support”. Przywrócenie kopii sprzed tygodnia nie pomaga, jeśli konto powstało wcześniej. Szukam go, porównując wp_users i wp_usermeta z ostatnią czystą kopią, a nie przeglądając listę w panelu.
Backdoor w uploadach. Plik PHP w rodzaju /wp-content/uploads/2024/03/.cache.php przyjmuje zakodowany kod przez POST i wykonuje go przez eval(). Przywrócenie samego rdzenia i wtyczek go nie usuwa. Szukam w uploads plików .php, .phtml i .phar i sprawdzam, czy serwer w ogóle pozwala je tam wykonać.
Wyciek .env przez publiczne repozytorium. Plik z hasłem do SMTP albo kluczem API trafia do publicznego repozytorium. Ktoś go znajduje, a skrzynka firmy zaczyna wysyłać spam. Pomaga wymiana kluczy, wyczyszczenie historii gita (git filter-repo) i hook, który nie przepuści .env do commita. W audycie szukam pod katalogiem strony plików .env, kopii wp-config.php i każdego pliku z DB_PASSWORD.
Jak wygląda raport z audytu bezpieczeństwa
Raport to dokument, który dostajesz e-mailem. Zawiera:
- listę ustaleń według priorytetu (krytyczne, wysokie, średnie, niskie), przy każdym opis problemu, numer CVE, jeśli istnieje, dowód (wersja, fragment konfiguracji, nagłówek, wpis w logu) i instrukcję poprawki dla developera,
- listę rzeczy, których nie dało się sprawdzić, na przykład z braku dostępu do logów albo panelu hostingu,
- krótkie podsumowanie dla osoby, która nie zajmuje się kodem: co poprawić najpierw, a co możesz świadomie zostawić.
Termin oddania raportu ustalam w ofercie. Na pytania do raportu odpowiadam e-mailem. Wdrożenie poprawek mogę wycenić osobno, a po nim sprawdzam ponownie punkty, których dotyczyło.
Strona zhakowana: co zrobić w pierwszej godzinie
- Niczego nie kasuj. Zrób kopię plików i bazy w obecnym stanie. Zainfekowane pliki pokazują, którędy weszli.
- Zmień hasła z czystego urządzenia: panel WordPress, hosting, SFTP, baza danych, klucze API płatności i poczty. Wyloguj wszystkie sesje.
- Wyłącz stronę albo włącz tryb konserwacji, jeśli serwuje malware, przekierowuje gości albo zbiera dane z formularzy i płatności.
- Poproś hosting o logi
access.logierror.logi zapytaj, jak długo je trzyma. Bez logów nie da się ustalić, co zostało odczytane. - Sprawdź Google Search Console. Obcy właściciel usługi to częsty ślad włamania. Usuń go po zabezpieczeniu kopii.
- Zapisz godzinę, o której stwierdziłeś włamanie. Od niej liczy się termin z RODO.
Jak wygląda sprzątanie po włamaniu
Pracuję na kopii, nie na produkcji. Najpierw ustalam, którędy weszli (logi, wp core verify-checksums, porównanie plików wtyczek i motywu), potem usuwam malware i backdoory z plików i bazy, sprawdzam konta administratorów i zadania cron, odtwarzam rdzeń i wtyczki z czystych źródeł i wymieniam wszystkie sekrety. Na końcu skanuję stronę ponownie, a jeśli Google ją oznaczył, składam wniosek o ponowne sprawdzenie. Ile to trwa, mówię dopiero po obejrzeniu strony, bo zależy od liczby zainfekowanych plików i od tego, czy są logi. Szczegóły są na stronie o usuwaniu wirusów WordPress.
Czy po włamaniu trzeba zgłosić wyciek danych
Administratorem danych jesteś Ty, więc decyzja o zgłoszeniu należy do Ciebie i do inspektora ochrony danych, jeśli go masz. Art. 33 ust. 1 RODO wymaga zgłoszenia naruszenia organowi nadzorczemu (w Polsce to Prezes UODO, art. 34 ust. 2 ustawy o ochronie danych osobowych) bez zbędnej zwłoki, w miarę możliwości w ciągu 72 godzin od jego stwierdzenia, chyba że jest mało prawdopodobne, by skutkowało ryzykiem dla praw lub wolności osób. Gdy ryzyko jest wysokie, art. 34 nakazuje zawiadomić także osoby, których dane dotyczą. Każde naruszenie, również niezgłoszone, trzeba udokumentować (art. 33 ust. 5).
Jako podmiot przetwarzający mam obowiązek z art. 33 ust. 2: gdy stwierdzę naruszenie, zgłaszam je Tobie bez zbędnej zwłoki. Dostajesz ode mnie to, czego potrzebuje prawnik: czy w bazie były dane osobowe, czy ktoś miał do nich dostęp i od kiedy.
Źródła: tekst RODO w EUR-Lex, wytyczne EROD 9/2022 o zgłaszaniu naruszeń, ustawa o ochronie danych osobowych, tekst jednolity Dz.U. 2019 poz. 1781 w ISAP.
Co po czyszczeniu
Wdrożyć hardening z sekcji wyżej: logowanie dwuskładnikowe, wyłączony edytor plików, regularne porównanie sum kontrolnych i ograniczenie prób logowania. Bez tego ta sama droga zostaje otwarta.
Jakie dostępy są potrzebne do audytu WordPress
Jeśli na stronie są dane osobowe, przed pierwszym logowaniem podpisuję umowę powierzenia z art. 28 RODO. Potem potrzebuję:
- Tymczasowego konta administratora w WordPressie, z logowaniem dwuskładnikowym. Zakładasz je na czas audytu i usuwasz po nim.
- Dostępu SSH albo SFTP, najlepiej tylko do odczytu. Pozwala sprawdzić sumy kontrolne przez WP-CLI, uprawnienia katalogów, logi i pliki w
/wp-content/uploads/. Bez niego część strony zostaje niewidoczna. - Listy integracji i ważniejszych wtyczek: nazwa, do czego służy, czy przyjmuje dane od użytkowników. Dzięki niej najpierw czytam kod tych wtyczek, które mają formularze albo endpointy REST.
Przydają się też dostęp do Google Search Console, poprzedni raport z audytu, jeśli był, i historia alertów z Wordfence, Sucuri albo Patchstack. Jeśli czegoś brakuje, zawężam zakres i zapisuję w raporcie, czego nie sprawdziłem.
Po co firmie audyt bezpieczeństwa WordPress
- Zaufanie klientów. Strona oznaczona przez Google Safe Browsing dostaje czerwone ostrzeżenie przed treścią i większość gości na nim się zatrzymuje. Powrót do normalnej widoczności po czyszczeniu trwa, a klienci B2B pamiętają takie ostrzeżenie dłużej niż Google.
- RODO i dane w sklepie. Wyciek danych z bazy WooCommerce albo z formularza może oznaczać zgłoszenie do Prezesa UODO w 72 godziny. Audyt pokazuje, gdzie dane leżą, kto ma do nich dostęp i gdzie trzymane są klucze API, w tym do KSeF i bramek płatności.
- Koszt włamania. To godziny pracy nad ustaleniem, którędy weszli, przestój sklepu w czasie czyszczenia, odbudowa widoczności i rozmowy z klientami, jeśli wyciekły ich dane. Poprawka znaleziona w audycie jest prawie zawsze tańsza.
Wyślij krótki opis strony, a odpiszę z pytaniami i ofertą na audyt albo na sprzątanie po włamaniu. Po audycie i poprawkach warto przejść na stałe utrzymanie WordPress, żeby zalecenia nie rozjechały się przy kolejnych zmianach wtyczek.
Zanim się odezwiesz, możesz sprawdzić stronę sam: sprawdzenie strony WordPress pobiera publiczną wersję jednego adresu i pokazuje nagłówki, przekierowania i ślady WordPressa. Nie wymaga podawania adresu e-mail.







