Bardzo wolne /wp-admin/ nie musi oznaczać malware, ale jeżeli wcześniej działało normalnie i nagle zaczęło się „wieszać”, warto potraktować to jako incydent do diagnostyki. Przyczyną może być plugin/theme, PHP-FPM, baza danych, cron, brak RAM/CPU/dysku, problem z DNS/HTTP albo faktycznie złośliwy kod.
Najlepiej diagnostykę zrobić z terminala, bez korzystania z panelu WordPressa. WP-CLI jest do tego wręcz stworzone — pozwala wykonywać operacje na WordPressie bez przeglądarki.
1. Najpierw sprawdź, czy problem leży w WordPressie
Wejdź do katalogu instalacji:
cd /var/www/html
oczywiście podając właściwą ścieżkę.
Sprawdź wersję:
wp core version
i czy WordPress poprawnie ładuje się z CLI:
wp core is-installed
Jeżeli to działa bardzo wolno, mamy już ważną wskazówkę.
Następnie:
time wp option get siteurl
oraz:
time wp option get home
Jeżeli proste polecenia WP-CLI wykonują się np. kilkanaście kilkadziesiąt sekund, problem prawdopodobnie nie dotyczy samego panelu /wp-admin/, tylko czegoś ładowanego podczas bootstrapu WordPressa.
2. Bardzo ważny test: wyłącz pluginy „w pamięci”
Nie musisz ich fizycznie wyłączać.
WP-CLI pozwala pominąć ładowanie pluginów:
wp option get siteurl --skip-plugins
i porównaj:
time wp option get siteurl
time wp option get siteurl --skip-plugins
Możesz zrobić to samo z motywami:
time wp option get siteurl --skip-themes
oraz z obydwoma:
time wp option get siteurl --skip-plugins --skip-themes
Jeżeli masz np.:
normalnie: 18.5 s
--skip-plugins: 0.4 s
--skip-themes: 17.9 s
to masz bardzo mocną wskazówkę, że problem powoduje plugin.
Jeżeli natomiast:
normalnie: 18 s
--skip-plugins: 17 s
--skip-themes: 17 s
szukałbym dalej — baza, PHP, sieć, cron, filesystem itd.
3. Sprawdź logi PHP-FPM i webservera
To jest jeden z pierwszych kroków, które zrobiłbym na serwerze.
Najpierw:
systemctl status php*-fpm
oraz:
journalctl -u php*-fpm --since "1 hour ago"
W zależności od dystrybucji PHP-FPM może mieć np. usługę:
php8.3-fpm
więc:
journalctl -u php8.3-fpm --since "1 hour ago"
Szukaj szczególnie:
PHP Fatal error
PHP Warning
Maximum execution time
Allowed memory size
Out of memory
segmentation fault
child exited
pool seems busy
server reached pm.max_children
Jeżeli używasz nginx:
tail -n 200 /var/log/nginx/error.log
Apache:
tail -n 200 /var/log/apache2/error.log
I równocześnie warto obserwować log podczas próby wejścia na /wp-admin/:
tail -f /var/log/nginx/error.log
W drugim terminalu otwierasz:
https://twojadomena.pl/wp-admin/
i patrzysz, co pojawia się w logu.
4. Sprawdź zasoby serwera
To banalne, ale bardzo często właśnie tutaj leży problem.
uptime
free -h
df -h
df -i
oraz:
top
albo:
htop
Szczególnie interesuje mnie:
free -h
Jeżeli zobaczysz praktycznie zerowy RAM i zaczyna się swapowanie, WordPress może działać dramatycznie wolno.
Sprawdź również:
dmesg -T | grep -Ei 'oom|out of memory|killed process'
Jeżeli znajdziesz:
Out of memory: Killed process ...
to prawdopodobnie masz problem z pamięcią, a nie wirusa.
5. Sprawdź bazę danych
Jeżeli wp-admin długo „myśli”, bardzo często winna jest baza.
WP-CLI pozwala wykonać:
wp db check
Możesz również sprawdzić rozmiar bazy:
wp db size
oraz szczególnie interesujące są autoloaded options.
WP-CLI Doctor ma nawet diagnostykę dotyczącą zbyt dużego rozmiaru automatycznie ładowanych opcji, ponieważ mogą one powodować problemy z wydajnością.
Jeżeli masz zainstalowany wp doctor, możesz sprawdzić:
wp doctor check --all
6. Teraz najważniejsze: sprawdzenie, czy WordPress został zmodyfikowany
Tutaj nie zaczynałbym od ClamAV.
Najpierw wykorzystaj mechanizm checksumów WordPressa.
wp core verify-checksums
WP-CLI porównuje pliki core WordPressa z checksumami opublikowanymi przez WordPress.org, bez ładowania całego WordPressa.
Prawidłowy wynik:
Success: WordPress installation verifies against checksums.
Podejrzany:
Warning: File doesn't verify against checksum: ...
Jeszcze lepiej:
wp core verify-checksums --include-root
Ta opcja sprawdza również pliki znajdujące się w katalogu głównym instalacji i może ostrzec o nieznanych plikach.
To jest bardzo wartościowy test w przypadku podejrzenia włamania.
7. Sprawdź pluginy
Uruchom:
wp plugin list
a następnie:
wp plugin verify-checksums --all
WP-CLI może porównać pliki pluginów z checksumami WordPress.org.
Tutaj jednak jest ważne zastrzeżenie.
Jeżeli masz plugin premium albo własny plugin, możesz zobaczyć:
Warning: Could not retrieve the checksums...
To nie oznacza automatycznie malware.
Po prostu WordPress.org może nie posiadać checksumów danego pluginu. Dotyczy to między innymi wielu komercyjnych i customowych pluginów.
8. Sprawdź motywy
wp theme list
Następnie warto przejrzeć:
find wp-content/themes -type f -name '*.php' -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
Szczególnie zwróć uwagę na niedawno zmodyfikowane pliki.
To samo dla pluginów:
find wp-content/plugins -type f -name '*.php' -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort
Jeżeli np. znany plugin ma 150 plików z datą sprzed roku, a nagle:
wp-content/plugins/some-plugin/x.php
2026-08-22 ...
to warto się temu przyjrzeć.
9. Poszukaj typowych śladów malware w PHP
Możesz zacząć od prostego grep:
grep -RniE 'base64_decode|eval\s*\(|gzinflate|str_rot13|shell_exec|passthru|proc_open|popen|assert\s*\(' wp-content
Ale uwaga: samo znalezienie base64_decode() nie oznacza infekcji.
Legalny plugin może używać:
base64_decode()
albo:
eval()
choć eval() jest już bardzo mocnym powodem do sprawdzenia kontekstu.
Ciekawszy jest wzorzec, np.:
eval(base64_decode(...))
WP-CLI Doctor ma nawet domyślny test wykrywający wzorzec eval(...base64_decode(...)).
Możesz więc zrobić:
grep -RniE 'eval\s*\(\s*base64_decode|eval\s*\(\s*gzinflate|base64_decode\s*\(\s*gzinflate' wp-content
10. Poszukaj świeżo utworzonych plików PHP
To jest bardzo dobry test po potencjalnym włamaniu.
Na przykład ostatnie 7 dni:
find /var/www/html -type f -name '*.php' -mtime -7 -ls
Ostatnie 24 godziny:
find /var/www/html -type f -name '*.php' -mtime -1 -ls
Jeszcze bardziej interesujące:
find /var/www/html -type f -name '*.php' -printf '%TY-%Tm-%Td %TH:%TM:%TS %u %p\n' | sort -r | head -100
Jeżeli zobaczysz dziwne nazwy:
wp-content/uploads/2026/08/x.php
wp-content/cache/.something.php
wp-includes/class-wp-xxxx.php
wp-content/plugins/xxxx/.tmp.php
– nie usuwaj ich od razu. Najpierw zrób kopię i sprawdź zawartość.
Szczególnie podejrzane jest PHP w:
wp-content/uploads/
Normalnie WordPress przechowuje tam przede wszystkim media. PHP pojawiające się tam bez uzasadnienia jest warte bardzo dokładnego sprawdzenia.
11. ClamAV – tak, ale jako dodatkowa warstwa
Na poziomie Linuxa możesz zainstalować ClamAV.
Debian/Ubuntu:
sudo apt update
sudo apt install clamav clamav-freshclam
Zaktualizuj sygnatury:
sudo freshclam
Następnie przeskanuj katalog WordPressa:
sudo clamscan -r /var/www/html
Możesz zapisać wynik:
sudo clamscan -r /var/www/html \
--log=/var/log/clamav/wordpress-scan.log
Jeżeli interesują Cię tylko znalezione infekcje:
sudo clamscan -r -i /var/www/html
ClamAV oficjalnie obsługuje skanowanie rekurencyjne przez --recursive i zapis raportu przez --log.
Nie rób od razu:
clamscan --move=...
Nie pozwalałbym antywirusowi automatycznie przenosić plików WordPressa.
Najpierw:
wykryj → zabezpiecz kopię → przeanalizuj → dopiero usuń/odtwórz.
12. Bardzo ważne: malware może być niewykrywalny przez ClamAV
To jest chyba najważniejsza rzecz w całej odpowiedzi.
Jeżeli:
clamscan
niczego nie znajdzie, nie oznacza to, że WordPress jest czysty.
ClamAV jest skanerem sygnaturowym/heurystycznym. Złośliwy kod PHP może być:
- nowy,
- zmodyfikowany,
- zakodowany,
- ukryty w legalnym pluginie,
- dodany jako nowy plik,
- zapisany w bazie danych,
- umieszczony w
wp_options, - wykonywany przez
mu-plugins, - albo pochodzić z konta systemowego.
Dlatego checksumy WordPressa + analiza plików + logi + ClamAV dają znacznie lepszy obraz niż sam antywirus.
13. Sprawdź mu-plugins
To często pomijane miejsce.
ls -la wp-content/mu-plugins/
i:
find wp-content/mu-plugins -type f -ls
mu-plugins są szczególnie istotne, bo są automatycznie ładowane przez WordPress i zwykłe:
wp plugin deactivate ...
ich nie wyłącza.
Dlatego jeśli:
wp option get siteurl --skip-plugins
nadal działa bardzo wolno, mu-plugins nadal mogą być przyczyną.
14. Sprawdź użytkowników WordPressa
Jeżeli podejrzewasz włamanie:
wp user list
Zwróć uwagę na nieznane konta administratorów.
Możesz wyświetlić administratorów:
wp user list --role=administrator
Jeżeli znajdziesz nieznane konto — nie kasuj go od razu, jeśli podejrzewasz aktywne włamanie. Najpierw zabezpiecz dowody i backup.
15. Sprawdź crony WordPressa
Atakujący bardzo często wykorzystują mechanizmy cron do okresowego uruchamiania kodu.
Jeżeli masz odpowiedni pakiet WP-CLI:
wp cron event list
Szczególnie interesują mnie:
- dziwne nazwy hooków,
- bardzo częste uruchamianie,
- adresy URL,
- callbacki związane z nieznanym pluginem.
WP-CLI Doctor ma również kontrole liczby cronów i duplikatów, bo ich nadmiar może być symptomem problemów.
16. Sprawdź też sam Linux
Jeżeli naprawdę podejrzewasz, że cała maszyna została zainfekowana, a nie tylko WordPress, rozszerzyłbym diagnostykę poza /var/www.
Na początek:
ps auxf
ss -tulpn
oraz:
ss -tpn
Sprawdź procesy uruchomione przez użytkownika webservera:
ps aux | grep -E 'www-data|nginx|apache'
Na Debian/Ubuntu:
sudo systemctl list-units --type=service --state=running
i:
sudo systemctl list-timers --all
Sprawdź cron:
sudo crontab -l
oraz:
sudo ls -la /etc/cron.d/
sudo ls -la /etc/cron.daily/
Jeżeli znalazłeś podejrzany proces, nie zabijaj go automatycznie. Najpierw:
ps -fp PID
oraz:
readlink -f /proc/PID/exe
17. Ja zrobiłbym to w takiej kolejności
Jeżeli to jest mój serwer i właśnie przestał działać /wp-admin/, moja pierwsza sesja SSH wyglądałaby mniej więcej tak:
cd /var/www/html
time wp option get siteurl
time wp option get siteurl --skip-plugins
time wp option get siteurl --skip-themes
wp core verify-checksums --include-root
wp plugin verify-checksums --all
wp plugin list
wp theme list
wp user list --role=administrator
wp db check
wp db size
find wp-content -type f -name '*.php' -mtime -7 -ls
grep -RniE \
'eval\s*\(\s*base64_decode|eval\s*\(\s*gzinflate|shell_exec|passthru|proc_open' \
wp-content
Potem:
free -h
df -h
df -i
uptime
i:
journalctl -u php8.3-fpm --since "1 hour ago"
oczywiście zmieniając wersję PHP na tę, którą faktycznie masz.
Na końcu:
sudo freshclam
sudo clamscan -r -i /var/www/html
A teraz najważniejsze
Jeżeli chcesz, możemy to zrobić razem krok po kroku, bez zgadywania.
Podeślij mi wynik tych 10 poleceń (możesz zamazać domenę, IP, username’y i dane wrażliwe):
cd /ścieżka/do/wordpressa
time wp option get siteurl
time wp option get siteurl --skip-plugins
time wp option get siteurl --skip-themes
wp core version
wp core verify-checksums --include-root
wp plugin list
wp theme list
wp user list --role=administrator
wp db check
free -h
Jeżeli wp wymaga użytkownika www-data, uruchom odpowiednio np.:
sudo -u www-data wp ...
Nie wklejaj tutaj zawartości wp-config.php, haseł do bazy, kluczy API ani sekretów.
Na podstawie tych wyników będę w stanie powiedzieć, czy bardziej wygląda to na plugin/PHP, bazę danych, zasoby serwera, uszkodzony WordPress czy potencjalne włamanie.