
SQL-инъекции остаются одним из самых опасных векторов атак, а классические SQL Firewall ограничены статическими правилами. Интеграция модели машинного обучения в СУБД позволяет выявлять вредоносные запросы без снижения производительности.
Введение
SQL-инъекции на протяжении многих лет остаются одним из наиболее распространённых и эффективных способов компрометации приложений и баз данных. Несмотря на развитие механизмов защиты, полностью исключить риск их возникновения на уровне приложений не удаётся, особенно в сложных и распределённых системах.
Традиционные подходы, такие как SQL Firewall со списком разрешённых запросов, обеспечивают высокий уровень контроля, но часто оказываются слишком жёсткими и плохо масштабируются в динамичной среде. Любое изменение бизнес-логики или структуры запросов требует ручной актуализации правил, что снижает удобство эксплуатации и гибкость системы.
Развитие методов машинного обучения открывает возможность перейти от статических правил к адаптивной фильтрации запросов на уровне СУБД. Анализ синтаксической структуры SQL-запросов позволяет выявлять инъекции даже в случаях, когда вредоносный запрос формально остаётся валидным, а его сигнатура не совпадает с заранее известными шаблонами.
Проблематика
В состав СУБД «Ятоба» входит расширение SQL Firewall, которое позволяет администратору баз данных составить список разрешённых запросов, после чего на уровне СУБД блокировать все запросы, не входящие в этот список (или только логировать их выполнение).
Решение достаточно прямолинейно, поэтому ему не хватает гибкости для повышения качества обнаружения вредоносного кода. Например, в ряде случаев жёсткое ограничение списка запросов неприменимо: более подходящим режимом работы будет ограничение именно опасного трафика, которым в контексте СУБД являются SQL-инъекции.
К началу 2026 года SQL-инъекции остаются наиболее распространённым и опасным вектором атак. В этой статье мы опишем, как решали данную задачу с помощью машинного обучения и каких результатов добились.
Обучение моделей
В сети существуют датасеты для обучения моделей, обнаруживающих SQL-инъекции, но к нашей задаче они не подходят. Эти датасеты ориентированы на выявление инъекций в пользовательском вводе (например, при логине). Мы решаем другую задачу: на момент поступления в СУБД запрос с инъекцией может быть таким же валидным, как и обычный, поэтому их значительно сложнее отличить друг от друга. Различия между обычными запросами и запросами с инъекциями проявляются не на уровне конкретных значений входных данных, а на синтаксическом уровне.
Мы создали датасет из обычных запросов и запросов с инъекциями. Для универсальности применения запросы были нормализованы. В итоге нами была получена модель с хорошей точностью, определяющая, содержит ли запрос payload инъекции.
Однако это только половина задачи. Необходимо встроить модель в СУБД «Ятоба», чтобы она могла работать в дочернем процессе СУБД и пресекать запросы с инъекциями до того, как они смогут нанести вред.
Предобработка и нормализация запросов
Одной из важных задач при подготовке датасета стала нормализация SQL-запросов. В реальных системах один и тот же запрос может отличаться только значениями параметров.
Например:
SELECT * FROM users WHERE id = 42;
SELECT * FROM users WHERE id = 105.
С точки зрения структуры такие запросы идентичны, однако для алгоритмов машинного обучения они являются разными строками. Это приводит к избыточному росту пространства признаков и ухудшению способности модели обобщать данные. Чтобы решить эту проблему, на этапе предобработки мы заменяли константные значения на $1, $2, ….
Например, запрос:
SELECT * FROM users WHERE login = 'admin' AND id = 42;
после нормализации преобразуется в:
SELECT * FROM users WHERE login = $1 AND id = $2.
Такая нормализация позволяет модели концентрироваться на структуре SQL-запроса, а не на конкретных значениях параметров. Это особенно важно при обнаружении SQL-инъекций, поскольку атакующие часто варьируют именно значения, а не синтаксическую форму запроса.
Формирование признаков
После нормализации запросы представляют собой текстовые строки. Для преобразования их в числовое представление мы использовали классический метод обработки текстов — TF-IDF (Term Frequency – Inverse Document Frequency).
Каждый SQL-запрос рассматривался как последовательность токенов. В качестве токенов использовались ключевые слова SQL, операторы, а также специальные маркеры, появляющиеся после нормализации.
Метод TF-IDF позволяет представить каждый запрос в виде вектора признаков. Значение каждого признака отражает:
- насколько часто токен встречается в конкретном запросе;
- насколько он характерен для всего корпуса запросов.
В результате часто встречающиеся служебные слова SQL получают меньший вес, а более специфичные конструкции (например, UNION, логические операторы или нетипичные комбинации токенов) становятся более значимыми для классификатора.
Используемый ML-пайплайн
Итоговая модель была реализована в виде следующего пайплайна:
TF‑IDF Vectorizer → Random Forest Classifier
На первом этапе текст запроса преобразуется в вектор признаков TF-IDF. Далее этот вектор подаётся на вход модели Random Forest, которая выполняет бинарную классификацию: содержит ли запрос признаки SQL-инъекции.
Random Forest хорошо подходит для данной задачи по нескольким причинам:
- устойчив к шуму в данных;
- способен работать с разреженными признаковыми матрицами;
- хорошо выявляет нелинейные зависимости между токенами;
- не требует сложной настройки гиперпараметров.
В процессе обучения модель научилась выделять характерные комбинации токенов, типичные для SQL-инъекций.
Выбор модели
На этапе экспериментов мы протестировали несколько различных алгоритмов классификации:
- Logistic Regression;
- Support Vector Machines;
- CatBoost;
- Random Forest.
Некоторые модели показывали сопоставимые метрики качества, однако при выборе итогового решения мы учитывали не только точность классификации, но и требования к интеграции модели в СУБД.
Ключевым ограничением стала необходимость экспорта модели в формат ONNX и её последующего выполнения через ONNX Runtime внутри расширения, написанного на языке C.
Часть моделей либо не поддерживала корректный экспорт в ONNX, либо требовала более сложных преобразований. Кроме того, некоторые алгоритмы демонстрировали более высокую вычислительную стоимость инференса (предсказания моделью целевого признака на неизвестных для неё данных).
В результате наиболее сбалансированным решением оказался пайплайн TF-IDF + Random Forest, который стабильно экспортируется в ONNX, обладает хорошими метриками качества и обеспечивает достаточно быстрый инференс.
Встраивание в SQL Firewall
Для того чтобы встроить нашу модель в расширение, написанное на C, мы используем движок ONNX Runtime. Он позволяет развёртывать модели, сохранённые в формате ONNX, на различных платформах, включая код на C и C++.
При инициализации расширения мы инициализируем сессию ONNX Runtime и разворачиваем модель. Далее, в процессе исполнения запросов, мы перехватываем их после разбора и до исполнения и выполняем инференс. Если score запроса выше порогового значения, исполнение прерывается, и в лог записывается ошибка, указывающая на потенциальную попытку SQL-инъекции.
Производительность
Поскольку модель выполняется непосредственно внутри СУБД, важным требованием было минимальное влияние на производительность. На практике вычисление признаков TF-IDF и выполнение модели Random Forest занимают доли миллисекунды на 1 запрос. Благодаря этому использование модели практически не влияет на время выполнения SQL-запросов и может применяться даже в высоконагруженных системах.
Пример работы
Продемонстрируем процесс, описанный выше, на небольшом примере. У нас создано расширение SQL Firewall, и в конфигурационных параметрах настроены значения для работы ML. Они настраиваются в postgresql.conf следующим образом:
# ml_enabled - флаг для включения отлова инъекций. По умолчанию - false
sql_firewall.ml_enabled = 'true'
# ml_score_threshold - верхняя граница значения score, которое будет трактоваться как безопасное (запрос без инъекций)
# Для всех score выше threshold расширение будет считать запрос небезопасным
# Значение по умолчанию - 0.5
sql_firewall.ml_score_threshold = 0.35
Выполним обычный запрос:
SELECT * FROM users WHERE id = 42;
id | name | email
----+------+------------------
42 | John | john@example.com
(1 row)
Score данного запроса оказался ниже порогового значения, и он успешно выполнился.
Теперь выполним запрос с инъекцией:
SELECT * FROM users WHERE username = 'admin' OR '1'='1';
ERROR: Обнаружена SQL-инъекция! Выполнение запроса прервано
Как можно заметить, данный запрос был заблокирован расширением с характерным сообщением об ошибке.
Выводы
В итоге мы дополнили SQL Firewall новым режимом работы, отсекающим только «плохие» запросы вместо допуска только «хороших». Данная функциональность почти не влияет на скорость исполнения запросов (в среднем на 5 %, в то время как средняя задержка увеличивается всего на 0,6 миллисекунды) и может использоваться для защиты от SQL-атак почти в любой конфигурации ИТ-инфраструктуры.
По состоянию на апрель 2026 года СУБД «Jatoba» — единственная СУБД общего назначения на российском рынке, имеющая SQL Firewall. Теперь он усилен технологиями искусственного интеллекта.






