Накратко: За да проверите базата данни за зловреден код, претърсете експорт или копие с четящи заявки за внедрени скриптове, чужди адреси и прикрит код в съдържание и настройки. Проверете освен това тригерите, планираните събития, съхранените процедури и потребителите на базата данни. Почиствайте едва след оценката и никога чрез сляпо търсене и замяна, защото сериализираните данни иначе се чупят.
Слепото петно на много почиствания
След пробив повечето оператори проверяват файловете. Заменят ядрото на CMS, изтриват съмнителни PHP файлове и инсталират наново разширенията. След това сайтът изглежда чист и седмица по-късно отново пренасочва към чужди страници. Причината често е в базата данни, която е била взета непроменена при почистването.
За атакуващите базата данни е привлекателно скривалище. Скрипт в една джаджа се връща на всяка страница. Променена настройка за адрес пренасочва всички посетители. Допълнителен администраторски акаунт отваря вратата за по-късно. Нищо от това не се забелязва при сканиране на файлове.
След PHP2Shell, уязвимостите CVE-2026-109618 и CVE-2026-109619 с изпълнение на код без вход в системата, базата данни затова е част от всяка проверка. Който може да изпълнява код на сървъра, по правило може да прочете данните за достъп до базата данни от конфигурацията и да пише в нея произволно. Как приложението изобщо общува с базата данни, обяснява PHP и бази данни: PDO и mysqli.
Къде се крие зловредният код в базата данни
| Място на находката | Типично съдържание | Ефект |
|---|---|---|
| Съдържание (публикации, страници, продукти) | блокове <script>, невидими връзки, <iframe> |
зловреден код или спам за посетителите |
| Настройки и опции | променен адрес на сайта, чужди скриптове в джаджи или опции на темата | пренасочвания, скриптове на всички страници |
| Потребителски таблици | допълнителни администратори | трайно достъпване |
| Тригери | код, който променя съдържание при всяко запазване | зловредният код се връща след почистване |
| Планирани събития | повтарящи се задачи в сървъра на базата данни | промени без уеб достъп |
| Потребители на базата данни | допълнителни акаунти с широки права | достъп в обход на CMS |
Последните три реда се пропускат особено често, защото не се намират в таблиците на CMS, а в самия сървър на базата данни.
При онлайн магазините едно място заслужава особено внимание: настройките, чрез които се вграждат допълнителни скриптове в касата и при завършване на поръчката. Чужд скрипт на това място може да прочете въведеното от клиентите, преди то да отиде криптирано към платежния доставчик. Затова проверявайте целенасочено всички полета за код в горния и долния колонтитул, вграждания за проследяване и настройки на дизайна, които действат на страниците на касата.
Мислете и за други бази данни на същия сървър. Тестови и staging копия, стари състояния на проекти или бази данни на други уебсайтове често са наблизо и са достъпни със същите данни за достъп. Което е намерено в продукционната база данни, трябва да се провери и там, преди някоя копие по-късно отново да послужи като основа.
Проверка на базата данни за зловреден код: съдържание и настройки
Работете върху експорт. Той е едновременно запазване на доказателства и основа за търсене. Експортът може да се претърсва като текстов файл, без да натоварва работещата база данни:
# Създаване на консистентен експорт (данните за достъп се питат)
mysqldump --single-transaction --routines --triggers --events -u BENUTZER -p DATENBANK > export.sql
sha256sum export.sql > export.sql.sha256
# Преброяване на типични модели в експорта
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
Последната заявка изброява всички домейни, които се срещат в базата данни, по честота. Чужди домейни, които никой в екипа не познава, са най-важните кандидати. За целенасочени заявки в самата база данни подхождат команди SELECT. Примерът ползва таблици на WordPress; префиксът и имената на таблиците на други системи са в тяхната документация:
-- Настройки със скриптове или подозрителни функции
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;
Записите с много голямо съдържание заслужават особено внимание. Контекст за скривалищата, специфични за WordPress, предлага ръководството Намиране на задни врати в WordPress.
Тригери, събития и акаунти в базата данни
Тригери и планирани събития в много уеб приложения изобщо не са предвидени. Ако съществуват, някой трябва да може да обясни защо. Тези заявки четат само от системните таблици на MySQL и MariaDB:
-- Тригери във всички бази данни
SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_OBJECT_TABLE, CREATED
FROM information_schema.TRIGGERS;
-- Планирани събития
SELECT EVENT_SCHEMA, EVENT_NAME, STATUS, CREATED, LAST_EXECUTED
FROM information_schema.EVENTS;
-- Съхранени процедури и функции
SELECT ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, CREATED
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA NOT IN ('mysql', 'sys', 'information_schema', 'performance_schema');
-- Потребители на базата данни
SELECT user, host FROM mysql.user ORDER BY user;
Ако Вашето приложение ползва PostgreSQL или друга система за бази данни, системните таблици и командите се наричат другояче; принципът остава същият. За анализа се препоръчва отделен потребител на базата данни, който може само да чете. Така дори печатна грешка в заявка не може да промени нищо, а проверката не оставя следи в данните.
Тригер, който добавя код при запазване на публикация, обяснява защо зловредният код се връща след всяко почистване. Непознатите потребители на базата данни принадлежат към проверката на акаунтите също като администраторските акаунти в CMS; повече по темата в Намиране на чужди администраторски акаунти в CMS и на сървъра.
Чисто почистване без унищожаване на данни
Почистването е най-деликатната част. Този ред се е доказал:
- Оценете находките: всяко попадение се класифицира като известно, безобидно обяснимо или чуждо. Кодовете за проследяване и карти често са легитимни.
- Затворете входа: доведете PHP до коригирано състояние (8.5.12, 8.4.27, 8.3.36, 8.2.35 или потвърден backport), рестартирайте всички worker процеси, актуализирайте приложението.
- Премахнете целенасочено: чуждо съдържание се почиства през приложението или с инструменти, които обработват правилно сериализирани данни. Чужди тригери, събития и акаунти се изтриват.
- Сменете данните за достъп: нова парола за базата данни, въведете я в конфигурацията на приложението, ограничете правата на потребителя на приложението до собствената му база данни.
- Проверете отново: повторете заявките за търсене след няколко дни.
Не заменяйте нищо чрез търсене и замяна в SQL експорта. Сериализираните PHP данни записват дължината на всеки низ. Ако дължината се промени, настройката става нечетима и сайтът може да спре.
Пренасочвания, които се появяват въпреки чиста база данни, имат причина в друг слой. Статията Уебсайтът пренасочва към чужди страници помага при ограничаването.
Как помага PHP SOS конкретно?
- Запазваме базата данни с контролна сума и претърсваме експорта за скриптове, чужди домейни и прикрит код.
- Проверяваме тригери, събития, процедури и потребители на базата данни, които са извън CMS.
- Почистваме находките в рамките на премахването на зловреден софтуер, без да повреждаме сериализирани данни.
- Ограничаваме правата на потребителя на приложението и повтаряме проверката след почистването.
Често задавани въпроси
Може ли зловреден код да се крие в базата данни?
Да. Атакуващите записват JavaScript в публикации, описания на продукти или джаджи, променят настройки за адреси за пренасочвания или създават администраторски акаунти. В MySQL и MariaDB допълнително тригери и планирани събития могат да променят данни. Сканиране на файлове не открива нищо от това.
Как да претърся базата данни, без да счупя нещо?
Работете върху експорт или копие и използвайте само SELECT заявки. Експортът освен това може да се претърсва като текстов файл с grep. Промени се правят едва когато всяка находка е оценена и има резервно копие.
Защо да не почиствам находките с търсене и замяна в експорта?
Много CMS съхраняват настройките като сериализирани PHP данни, при които се записва и дължината на всеки низ. Замяната променя дължината, но не и записаната стойност, и настройката става нечетима. Почиствайте през приложението или с инструменти, които разбират сериализирани данни.
Подозрителен ли е всеки скрипт в базата данни?
Не. Кодове за проследяване, карти, видеа или чат джаджи също се съхраняват като скрипт. Решаващо е дали някой в екипа познава записа и целевия адрес.