Aktualna sytuacja: PHP2Shell. Dwie krytyczne luki w PHP (CVSS 9,2) umożliwiają wykonanie złośliwego kodu bez logowania. Poprawki od 21.10.2026.Co należy teraz zrobić →

Sprawdzanie bazy danych pod kątem wstrzykniętego kodu

Kto sprawdza tylko pliki, pomija połowę. Jak przeszukać treści, ustawienia, wyzwalacze i konta bazy danych pod kątem wstrzykniętego kodu, w trybie do odczytu i na kopii.

Stan 5 min czytaniaWykrywanie i informatyka śledcza

Krótko: Aby sprawdzić bazę danych pod kątem złośliwego kodu, przeszukują Państwo eksport lub kopię zapytaniami tylko do odczytu, szukając wstrzykniętych skryptów, obcych adresów i zaciemnionego kodu w treściach i ustawieniach. Należy też sprawdzić wyzwalacze, zaplanowane zdarzenia, procedury składowane i użytkowników bazy danych. Oczyszczać można dopiero po ocenie i nigdy przez ślepe wyszukiwanie i zamianę, ponieważ dane serializowane zostałyby uszkodzone.

Martwy punkt wielu oczyszczeń

Po włamaniu większość operatorów sprawdza pliki. Wymieniają rdzeń CMS, usuwają podejrzane pliki PHP i instalują rozszerzenia od nowa. Strona wygląda potem czysto, a tydzień później znów przekierowuje na obce witryny. Przyczyna leży często w bazie danych, którą podczas oczyszczania przejęto bez zmian.

Dla atakujących baza danych jest atrakcyjną kryjówką. Skrypt w widżecie jest dostarczany na każdej stronie. Zmienione ustawienie adresu przekierowuje wszystkich odwiedzających. Dodatkowe konto administratora otwiera drzwi na później. Nic z tego nie wychodzi na jaw przy skanie plików.

Po PHP2Shell, czyli lukach CVE-2026-109618 i CVE-2026-109619 umożliwiających wykonanie kodu bez logowania, baza danych należy więc do każdej kontroli. Kto może wykonać kod na serwerze, zazwyczaj może odczytać z konfiguracji dane dostępowe do bazy i dowolnie w niej zapisywać. Jak aplikacja w ogóle komunikuje się z bazą danych, wyjaśnia artykuł PHP i bazy danych: PDO i mysqli.

Gdzie złośliwy kod ukrywa się w bazie danych

Miejsce Typowa zawartość Skutek
Treści (wpisy, strony, produkty) bloki <script>, niewidoczne linki, <iframe> złośliwy kod lub spam dla odwiedzających
Ustawienia i opcje zmieniony adres strony, obce skrypty w widżetach lub opcjach motywu przekierowania, skrypty na wszystkich stronach
Tabele użytkowników dodatkowi administratorzy trwały dostęp
Wyzwalacze kod, który przy każdym zapisie zmienia treści złośliwy kod wraca po oczyszczeniu
Zaplanowane zdarzenia cykliczne zadania na serwerze bazy danych zmiany bez dostępu przez sieć WWW
Użytkownicy bazy danych dodatkowe konta z szerokimi uprawnieniami dostęp z pominięciem CMS

Ostatnie trzy wiersze są szczególnie często pomijane, ponieważ nie leżą w tabelach CMS, lecz w samym serwerze bazy danych.

W sklepach internetowych jedno miejsce zasługuje na szczególną uwagę: ustawienia, za pomocą których do kasy i finalizacji zamówienia dołączane są dodatkowe skrypty. Obcy skrypt w tym miejscu może podejrzeć dane wpisywane przez klientów, zanim zostaną zaszyfrowane i przekazane do operatora płatności. Dlatego proszę celowo sprawdzić wszystkie pola na kod nagłówka i stopki, osadzenia śledzące oraz ustawienia projektu graficznego, które działają na stronach kasy.

Proszę też pamiętać o innych bazach danych na tym samym serwerze. Kopie testowe i stagingowe, stare wersje projektów lub bazy innych stron leżą często obok i są osiągalne tymi samymi danymi dostępowymi. To, co znajdzie się w bazie produkcyjnej, należy sprawdzić także tam, zanim kopia posłuży później znowu jako podstawa.

Sprawdzanie bazy danych pod kątem złośliwego kodu: treści i ustawienia

Proszę pracować na eksporcie. Jest on zarazem zabezpieczeniem dowodów i podstawą wyszukiwania. Eksport można przeszukać jako plik tekstowy bez obciążania działającej bazy danych:

# Utworzyć spójny eksport (dane dostępowe zostaną zapytane)
mysqldump --single-transaction --routines --triggers --events -u BENUTZER -p DATENBANK > export.sql
sha256sum export.sql > export.sql.sha256

# Zliczyć typowe wzorce w eksporcie
grep -oiE '<script[^>]{0,80}' export.sql | sort | uniq -c | sort -rn | head -30
grep -oiE '(eval\(|base64_decode|fromCharCode|document\.write|atob\()' export.sql | sort | uniq -c
grep -oiE 'https?://[a-z0-9.-]+' export.sql | sort | uniq -c | sort -rn | head -50

Ostatnie zapytanie wypisuje według częstotliwości wszystkie domeny występujące w bazie danych. Obce domeny, których nikt w zespole nie zna, są najważniejszymi kandydatami. Do celowanych zapytań w samej bazie danych nadają się polecenia SELECT. Przykład używa tabel WordPress; prefiks i nazwy tabel innych systemów podano w ich dokumentacji:

-- Ustawienia ze skryptami lub podejrzanymi funkcjami
SELECT option_name, LENGTH(option_value) AS laenge
FROM wp_options
WHERE option_value LIKE '%<script%'
   OR option_value LIKE '%eval(%'
   OR option_value LIKE '%base64_decode%'
ORDER BY laenge DESC;

Wpisy o bardzo dużej zawartości zasługują na szczególną uwagę. Tło dotyczące kryjówek specyficznych dla WordPress przedstawia poradnik Wyszukiwanie backdoorów w WordPress.

Wyzwalacze, zdarzenia i konta bazy danych

Wyzwalacze i zaplanowane zdarzenia nie są w wielu aplikacjach internetowych w ogóle przewidziane. Jeśli istnieją, ktoś powinien umieć wyjaśnić, dlaczego. Poniższe zapytania odczytują dane wyłącznie z tabel systemowych MySQL i MariaDB:

-- Wyzwalacze we wszystkich bazach danych
SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_OBJECT_TABLE, CREATED
FROM information_schema.TRIGGERS;

-- Zaplanowane zdarzenia
SELECT EVENT_SCHEMA, EVENT_NAME, STATUS, CREATED, LAST_EXECUTED
FROM information_schema.EVENTS;

-- Procedury i funkcje składowane
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, CREATED
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('mysql', 'sys', 'information_schema', 'performance_schema');

-- Użytkownicy bazy danych
SELECT user, host FROM mysql.user ORDER BY user;

Jeśli aplikacja używa PostgreSQL lub innego systemu baz danych, tabele systemowe i polecenia nazywają się inaczej; zasada pozostaje ta sama. Do analizy zaleca się osobnego użytkownika bazy danych, który może tylko czytać. Dzięki temu nawet literówka w zapytaniu niczego nie zmieni, a kontrola nie zostawia śladów w danych.

Wyzwalacz, który przy zapisie wpisu dołącza kod, wyjaśnia, dlaczego złośliwy kod wraca po każdym oczyszczeniu. Nieznani użytkownicy bazy danych należą do kontroli kont tak samo jak konta administratorów w CMS; więcej w artykule Wyszukiwanie obcych kont administratorów w CMS i na serwerze.

Czyste oczyszczanie bez niszczenia danych

Oczyszczanie jest najbardziej delikatną częścią. Sprawdziła się następująca kolejność:

  1. Ocenić znaleziska: każde trafienie klasyfikuje się jako znane, nieszkodliwe i możliwe do wyjaśnienia lub obce. Kody śledzące i map są często uzasadnione.
  2. Zamknąć furtkę: doprowadzić PHP do naprawionej wersji (8.5.12, 8.4.27, 8.3.36, 8.2.35 lub potwierdzony backport), zrestartować wszystkie procesy robocze, zaktualizować aplikację.
  3. Usunąć celowo: obce treści oczyszczać przez aplikację lub narzędziami, które poprawnie traktują dane serializowane. Obce wyzwalacze, zdarzenia i konta usunąć.
  4. Zmienić dane dostępowe: nowe hasło do bazy danych wpisać w konfiguracji aplikacji, ograniczyć uprawnienia użytkownika aplikacji do własnej bazy danych.
  5. Sprawdzić ponownie: powtórzyć zapytania wyszukujące po kilku dniach.
Ważne

Niczego nie należy zastępować przez wyszukiwanie i zamianę w eksporcie SQL. Serializowane dane PHP zapisują długość każdego ciągu znaków. Jeśli długość się zmieni, ustawienie staje się nieczytelne, a strona może przestać działać.

Przekierowania, które występują mimo czystej bazy danych, mają przyczynę w innej warstwie. Przy zawężaniu pomoże artykuł Strona przekierowuje na obce witryny.

Jak konkretnie pomaga PHP SOS?

  • Zabezpieczamy bazę danych z sumą kontrolną i przeszukujemy eksport pod kątem skryptów, obcych domen i zaciemnionego kodu.
  • Sprawdzamy wyzwalacze, zdarzenia, procedury i użytkowników bazy danych, którzy leżą poza CMS.
  • Oczyszczamy znaleziska w ramach usuwania malware, nie uszkadzając danych serializowanych.
  • Ograniczamy uprawnienia użytkownika aplikacji i powtarzamy kontrolę po oczyszczeniu.

Częste pytania

Czy złośliwy kod może siedzieć w bazie danych?

Tak. Atakujący wpisują JavaScript do wpisów, opisów produktów lub widżetów, zmieniają ustawienia adresów na potrzeby przekierowań albo zakładają konta administratorów. W MySQL i MariaDB dodatkowo wyzwalacze (triggery) i zaplanowane zdarzenia mogą zmieniać dane. Skan plików niczego z tego nie znajdzie.

Jak przeszukać bazę danych, niczego nie psując?

Proszę pracować na eksporcie lub kopii i używać wyłącznie zapytań SELECT. Eksport można ponadto przeszukać jako plik tekstowy za pomocą grep. Zmiany wprowadza się dopiero po ocenie każdego znaleziska i wykonaniu kopii zapasowej.

Dlaczego nie powinienem oczyszczać znalezisk przez wyszukiwanie i zamianę w eksporcie?

Wiele systemów CMS zapisuje ustawienia jako serializowane dane PHP, w których zapisywana jest też długość każdego ciągu znaków. Zamiana zmienia długość, ale nie zmienia zapisanej wartości, i ustawienie staje się nieczytelne. Oczyszczać należy przez aplikację lub narzędziami rozumiejącymi dane serializowane.

Czy każdy skrypt w bazie danych jest podejrzany?

Nie. Kody śledzące, mapy, filmy czy widżety czatu także są zapisywane jako skrypt. Decydujące jest, czy ktoś w zespole zna ten wpis i adres docelowy.

Źródła

Kontakt natychmiast

Liczy się każda godzina. Proszę napisać do nas teraz.

Proszę krótko opisać system, wersję PHP i obserwacje. Skontaktujemy się z Państwem, ustalimy sytuację i będziemy pracować zdalnie, aż incydent zostanie zamknięty i udokumentowany.

Natychmiastowa pomoc