Malware wraca mimo czyszczenia?Zgłoś infekcję
← Blog
Bezpieczeństwo

Malware wraca po usunięciu? Fałszywa wtyczka, .user.ini i drop-iny w WordPressie

Fałszywa wtyczka siedziała w 11 miejscach i 35 wierszach bazy. Usunięcie jednej kopii kończyło się odbudową z pozostałych. Gdzie szukać i dlaczego verify-checksums tego nie widzi.

Malware w WordPressie wraca po usunięciu, gdy ma więcej niż jedną kopię i każda potrafi odbudować pozostałe. Usunięcie jednej nic nie daje, bo reszta ją przywraca. Trzeba znaleźć wszystkie miejsca startu (mu-plugins, pliki drop-in, .user.ini, wp-config.php, bazę danych), usunąć je w jednym przebiegu i od razu włączyć monitoring zmian w plikach. Poniżej dwa przypadki z naszych interwencji i lista miejsc, których nie sprawdza ani wp core verify-checksums, ani typowa wtyczka bezpieczeństwa.

Jak wyglądała samoodtwarzająca się fałszywa wtyczka?

Na stronie działała wtyczka, której nikt nie instalował. Po przejrzeniu serwera znaleźliśmy ją w 11 miejscach, w tym:

  • w katalogu wp-content/mu-plugins/, czyli wśród wtyczek ładowanych zawsze i niewidocznych na zwykłej liście wtyczek,
  • w plikach drop-in w wp-content (pliki typu object-cache.php czy advanced-cache.php, które WordPress ładuje sam, jeśli istnieją),
  • w pliku .user.ini z dyrektywą auto_prepend_file.

Do tego 35 wierszy w tabeli wp_options. Kopie odtwarzały się nawzajem: usunięcie jednej lokalizacji kończyło się jej odbudową z pozostałych.

Czym są mu-plugins, drop-iny i .user.ini?

Wszystkie te miejsca uruchamiają kod PHP bez wiedzy właściciela strony, a większość nie zostawia śladu na liście wtyczek.

MiejsceKiedy się uruchamiaCzy widać w panelu?
wp-content/mu-plugins/przy każdym ładowaniu WordPressa, nie da się go wyłączyć z panelutylko na osobnej liście w ekranie wtyczek, łatwo przeoczyć
drop-iny w wp-content/gdy WordPress znajdzie plik o zastrzeżonej nazwie, np. przy cachena osobnej liście w ekranie wtyczek, bez opisu, co robi kod
.user.iniprzed każdym skryptem PHP, jeszcze przed WordPressemnie
wp-config.phpprzy każdym żądaniu do WordPressanie
tabela wp_optionsgdy kod z plików odczyta zapisaną kopięnie

Najgroźniejszy jest .user.ini. Działa na poziomie PHP, więc wyłączenie wszystkich wtyczek, zmiana motywu czy nawet podmiana rdzenia WordPressa niczego nie zmienia. PHP-FPM czyta ten plik dla katalogu, w którym leży skrypt, a dyrektywa auto_prepend_file dokleja wskazany plik przed każdym wywołaniem PHP. Dodatkowo PHP trzyma odczytane ustawienia w pamięci przez czas z user_ini.cache_ttl (domyślnie 300 sekund), więc po usunięciu pliku złośliwy kod może działać jeszcze kilka minut. Wygląda to tak, jakby usuwanie nie działało.

Masz ten sam problem? Sprawdzimy mu-plugins, drop-iny, konfigurację PHP i bazę, zanim cokolwiek skasujemy. Opisz sytuację →

Dlaczego wp core verify-checksums nie wykrył infekcji?

Bo nie do tego służy. wp core verify-checksums porównuje pliki rdzenia WordPressa z sumami kontrolnymi z wordpress.org. Zgłosi zmieniony wp-includes/load.php, ale nie zobaczy nowego pliku w mu-plugins, drop-inu w wp-content ani .user.ini w katalogu głównym. Rdzeń może być czysty, a strona zarażona.

Podobnie wp plugin verify-checksums --all: sprawdza wtyczki z repozytorium wordpress.org, a mu-plugins i drop-inów nie obejmuje. Oba polecenia są przydatne, ale „Success” z nich nie oznacza czystej strony. Oznacza czysty rdzeń.

Jak znaleźć wszystkie kopie malware?

Zacznij od miejsc, których nie sprawdzają skanery rdzenia. Te polecenia tylko czytają, niczego nie zmieniają:

# pliki .user.ini i php.ini z auto_prepend_file w całym katalogu strony
find . \( -name ".user.ini" -o -name "php.ini" \) -exec grep -l "auto_prepend_file" {} +

# zawartość mu-plugins i drop-iny w wp-content
ls -la wp-content/mu-plugins/
ls -la wp-content/*.php

# co WordPress ładuje jako mu-plugins i drop-iny
wp plugin list --status=must-use,dropin

# koniec wp-config.php: wszystko po linii z wp-settings.php jest podejrzane
tail -n 20 wp-config.php

Nie każde trafienie to malware. Firewall Wordfence też używa auto_prepend_file (plik wordfence-waf.php), więc sprawdź, na jaki plik wskazuje dyrektywa i co jest w środku.

W bazie szukaj opcji, których nie potrafisz przypisać do żadnej znanej wtyczki, oraz nietypowo dużych wartości. Prefiks tabel może być inny niż wp_:

SELECT option_name, LENGTH(option_value) AS rozmiar
FROM wp_options
ORDER BY rozmiar DESC
LIMIT 30;

Długi ciąg znaków bez spacji w opcji lub transiencie to sygnał, że w bazie leży zakodowana kopia pliku. Zanim cokolwiek usuniesz, zrób kopię plików i bazy, bo będzie potrzebna do ustalenia, którędy weszło malware.

Jak usunąć malware, żeby nie wróciło?

Wszystko naraz. Kolejność, którą stosowaliśmy w tym przypadku:

  1. Inwentarz. Lista wszystkich 11 lokalizacji w plikach i 35 wierszy w bazie, spisana przed pierwszym kasowaniem.
  2. Neutralizacja .user.ini na poziomie PHP. W konfiguracji PHP ustawiliśmy user_ini.filename = (pusta wartość), żeby PHP w ogóle przestał czytać pliki .user.ini. Wtedy nawet odtworzony plik nic nie zrobi. Po zmianie trzeba przeładować PHP-FPM.
  3. Usunięcie wszystkich kopii w jednym przebiegu. Pliki i wiersze w bazie w ciągu jednej operacji, bez przerw, w których pozostałe kopie mogłyby odbudować usunięte.
  4. Monitoring integralności plików co 10 minut. Skrypt porównuje pliki z bazą odniesienia i alarmuje przy nowych lub zmienionych plikach, także w mu-plugins, drop-inach i .user.ini.
; php.ini albo konfiguracja puli PHP-FPM
user_ini.filename =

Uwaga: wyłączenie .user.ini dotyczy wszystkich stron obsługiwanych przez tę konfigurację PHP. Jeśli któraś legalnie ustawia w nim np. limit pamięci, przenieś to ustawienie do php.ini lub konfiguracji puli.

Co, jeśli usunięty plik wraca po kilku minutach?

Szukaj kodu, który go zapisuje. Drugi przypadek, z innej strony: plik dropper wracał po każdym usunięciu. Przyczyną był kod dopisany na końcu wp-config.php. Sprawdzał, czy dropper istnieje, a jeśli nie, zapisywał go ponownie z kopii base64 trzymanej w bazie danych jako transient.

Kasowanie samego pliku nie mogło zadziałać, bo wp-config.php wykonuje się przy każdym wejściu na stronę. Usunąć trzeba razem kod z wp-config.php, transient z bazy i sam plik. Kolejne kopie pliku to objaw. Źródłem jest kod, który je zapisuje.

Czy wtyczka bezpieczeństwa wystarczy?

Na taką infekcję zwykle nie. Skanery wtyczek dobrze rozpoznają znane pliki, ale działają wewnątrz WordPressa, więc nie mają wpływu na .user.ini, który wykonuje się przed nimi. Gorzej radzą sobie też z kopiami zakodowanymi w bazie. Po ich „wyczyszczeniu” zostaje kopia, która odbudowuje resztę.

Jeśli malware wróciło więcej niż raz, nie usuwaj kolejnych plików na ślepo. Każda próba bez pełnej listy lokalizacji daje infekcji czas na odbudowę, a przy okazji zaciera ślady. Ogólny przebieg sprzątania po włamaniu opisaliśmy w tekście o tym, jak rozpoznać i usunąć wirusa z WordPressa. Jeśli wolisz to zlecić, ASAPDevs robi usuwanie malware z WordPressa z inwentarzem wszystkich kopii i monitoringiem po sprzątaniu, a sklepy na WooCommerce bierzemy też w stałą opiekę. Gdy strona leży i nie ma na co czekać, dzwoń na pogotowie IT.

Źródła

Kamil Perzowski
Kamil Perzowski
CEO i co-founder ASAPDevs. Programuje i utrzymuje sklepy, aplikacje webowe i serwery klientów. LinkedIn · Zgłoś infekcję
Masz ten sam problem?

Malware wraca mimo czyszczenia?

Kamil Perzowski, ASAPDevs
Kamil Perzowski
CEO & Co-founder, ASAPDevs
Szukamy wszystkich kopii naraz: w plikach, w konfiguracji PHP i w bazie. Usuwamy je w jednym przebiegu i ustawiamy monitoring zmian. Pilne? Zadzwoń: +48 884 220 764.
★★★★★
Kapitalny kontakt, błyskawiczne wykonanie, super cena. Na pewno skorzystam ponownie. Polecam z czystym sumieniem!
Marcin P., opinia w Google
  1. Czytam zgłoszenie i odpisuję z pytaniami albo propozycją terminu rozmowy.
  2. Krótka rozmowa o zakresie, dostępach i terminie.
  3. Dostajesz plan i wycenę. Decydujesz, bez zobowiązań.

Wolisz od razu porozmawiać? +48 884 220 764 · [email protected]

Wysyłając formularz, przekazujesz nam dane, żebyśmy mogli odpowiedzieć. Szczegóły w polityce prywatności.

FAQ

Pytania i odpowiedzi

Dlaczego malware w WordPressie wraca po usunięciu?

+
Bo zostało usunięte z jednego miejsca, a działa z kilku. W opisanym przypadku fałszywa wtyczka siedziała w 11 miejscach, w tym w mu-plugins, w plikach drop-in i w .user.ini, a do tego w 35 wierszach tabeli wp_options. Każda pozostawiona kopia odtwarzała resztę.

Czy wp core verify-checksums wykryje malware w mu-plugins?

+
Nie. Polecenie porównuje tylko pliki rdzenia WordPressa z oficjalnymi sumami kontrolnymi. Nowych plików w wp-content/mu-plugins, drop-inów w wp-content ani pliku .user.ini w ogóle nie sprawdza.

Co to jest .user.ini i dlaczego atakujący go używa?

+
To plik z ustawieniami PHP dla katalogu, czytany przy PHP-FPM i CGI. Dyrektywa auto_prepend_file każe PHP dołączyć wskazany plik przed każdym skryptem, więc złośliwy kod uruchamia się przy każdym żądaniu, nawet gdy wtyczki są wyłączone.

Jak wyłączyć obsługę .user.ini?

+
Ustaw w php.ini albo w konfiguracji puli PHP-FPM pustą wartość user_ini.filename. PHP przestaje wtedy szukać plików .user.ini. Sprawdź wcześniej, czy żadna strona na serwerze nie korzysta z nich legalnie.

Usunąłem plik z malware, a po chwili znów jest. Co sprawdzić?

+
Plik wp-config.php i bazę danych. W jednym z naszych przypadków kod dopisany na końcu wp-config.php odtwarzał plik dropper z kopii base64 zapisanej w bazie jako transient. Samo kasowanie pliku nic nie dawało.

Przeczytaj też