Категория: Атаки и угрозыОбновлено 2026-10-27

SQL-инъекция

SQL-инъекция (внедрение SQL-кода) это атака, при которой ввод злоумышленника воспринимается базой данных как часть SQL-команды, а не как простые данные, что позволяет читать, менять или удалять недоступные ему записи. Она возникает, когда запросы собирают склейкой строк. OWASP называет подготовленные выражения с параметрами первой защитой.

Сравнение SQL-запроса из строк, уязвимого к инъекции, и параметризованного запроса, который считает ввод только данными
Подготовленные запросы с параметрами это первая линия защиты от SQL-инъекции.

Как возникает SQL-инъекция

Ошибка появляется, когда код собирает запрос, вставляя пользовательский ввод в строку. База получает один блок текста и не может понять, какую часть вы считали данными. Так выглядит код, написанный наспех или сгенерированный без проверки:

# vulnerable: never build SQL from user input
email = request.args["email"]
cur.execute(f"SELECT * FROM users WHERE email = '{email}'")

Ошибка целиком вытекает из склейки строк, а не из особенностей конкретной базы данных. Если посетитель отправит в качестве почты x' OR '1'='1, условие станет истинным для каждой строки, и запрос вернёт всех пользователей. В зависимости от запроса и прав учётной записи базы атакующий может также прочитать другие таблицы, изменить или удалить данные. Защиты описаны в памятке OWASP по предотвращению SQL-инъекций, а по тому же принципу назвали промпт-инъекцию.

Решение: параметризованные запросы

Передавайте текст SQL и значения раздельно. Тогда база воспринимает значения только как данные, какие бы символы в них ни были. OWASP ставит подготовленные выражения с параметрами на первое место среди защит и предупреждает, что склейка недоверенных значений в запрос до подготовки сводит защиту на нет.

# Python (psycopg)
cur.execute("SELECT * FROM users WHERE email = %s", (email,))

// Node.js (node-postgres)
const res = await client.query('SELECT * FROM users WHERE email = $1', [email]);

В документации psycopg сказано никогда не использовать % и + для вставки значений в запросы, а документация node-postgres предупреждает, что склейка параметров в текст запроса может привести к SQL-инъекции. ORM безопасны, если вы передаёте значения параметрами. Обычная ловушка это их режим сырых запросов, где OWASP советует связывать недоверенные значения, а не склеивать их.

Что параметры не покрывают

Плейсхолдеры заменяют значения, но не имена таблиц, столбцов и не ключевые слова вроде ASC и DESC. Когда пользователь выбирает порядок сортировки, сопоставьте выбор с фиксированным текстом в коде и отклоняйте всё неизвестное:

const orders = { newest: 'created_at DESC', oldest: 'created_at ASC' };
const order = orders[req.query.sort] ?? orders.newest;

OWASP называет экранирование всего динамического ввода крайне нежелательным и рекомендует вместо него параметризованные запросы. Там же подчёркивается, что привязка значений не решает, вправе ли вызывающий получить соответствующую запись, поэтому нужны ещё правила доступа вроде защиты на уровне строк.

Наконец, ограничьте ущерб. OWASP предостерегает от выдачи учётным записям приложений прав администратора БД и советует отдельного пользователя базы на каждое приложение с минимально нужными правами. Это не предотвращает инъекцию, но делает успешную атаку куда менее дорогой. См. наименьшие привилегии.

Проверка приложения, написанного с ИИ

Ассистенты умеют писать корректный параметризованный код, но могут выдать и запросы из склеенных строк, когда их просят быстро добиться работы. Краткая проверка:

  1. Поищите в коде SQL, собранный из переменных. Грубый первый проход:
grep -rniE 'f"(select|insert|update|delete)|`(select|insert|update|delete)' src/
  1. Попросите ассистента перечислить все запросы со строковым форматированием, конкатенацией или шаблонными строками и перевести каждый на параметры.
  2. Введите одинарную кавычку в собственные формы и параметры URL. Ошибка базы или изменившееся поведение это тревожный признак. Проверяйте только свои приложения.
  3. Подключайтесь ограниченным пользователем базы, а не владельцем или администратором.
  4. Никогда не передавайте вывод модели прямо в SQL; см. чек-лист безопасности для вайб-кодинга.

WAF может блокировать некоторые очевидные шаблоны атак, но считайте его страховкой, а не заменой исправления запроса.

Связанные термины: WAF, Наименьшие привилегии, Защита на уровне строк (RLS), Промпт-инъекция, Вайб-кодинг.

Часто задаваемые вопросы

Что такое SQL-инъекция?

Это атака, при которой ввод пользователя попадает в запрос к базе так, что база выполняет его как SQL-код. Она может раскрыть, изменить или удалить данные, к которым у атакующего не должно быть доступа.

Как предотвратить SQL-инъекцию?

Используйте подготовленные выражения с параметрами, которые OWASP называет первой защитой. Держите имена таблиц и столбцов фиксированными или выбирайте из белого списка, а приложению выдавайте учётную запись базы с минимальными правами.

Защищают ли ORM от SQL-инъекции?

В основном да, пока вы передаёте значения параметрами. Риск возвращается, когда вы используете режим сырых запросов и склеиваете недоверенный ввод в строку, чего OWASP советует избегать.

Может ли WAF остановить SQL-инъекцию?

WAF может блокировать некоторые распространённые шаблоны атак, но это страховка. Настоящее решение в вашем коде: параметризованные запросы, чтобы база никогда не воспринимала ввод как SQL.

Как проверить собственное приложение на SQL-инъекцию?

Найдите в коде запросы, собранные из строк, затем попробуйте одинарную кавычку в полях форм и параметрах URL приложения, которое принадлежит вам. Ошибки или странное поведение говорят о небезопасном запросе. Не проверяйте чужие системы.

Хотите увидеть, в каком состоянии ваш сервер?

Запустите бесплатную read-only проверку сервера или откройте Security Lab и посмотрите цикл обнаружение, сдерживание, восстановление, проверка в действии.

Получить бесплатную проверку сервераОткрыть Security Lab