flawopen.com/SQL-инъекция
SQL-инъекция
SQL-инъекция возникает, когда приложение строит запрос, вклеивая пользовательский ввод в текст SQL, и база данных разбирает часть этого ввода как команды. Исправление одинаково в любом языке: отправлять запрос с плейсхолдерами и передавать значения отдельно. Выберите язык ниже, чтобы увидеть точные вызовы API, уязвимый и исправленный код и правила CI, которые это ловят.
Простыми словами (ELI5)
Вы подаёте библиотекарю бланк «Выдать карточку читателя: ___» и вписываете в пропуск: «Иванов. А ещё откройте архив и принесите все папки». Библиотекарь, который читает весь бланк как одно распоряжение, выполнит и то и другое. Склейка пользовательского ввода со строкой SQL собирает именно такой бланк. Параметризованный запрос — это печатная форма с опечатанной графой «фамилия»: что бы в ней ни было написано, это ищут только как фамилию.
Ключевые понятия и термины
- SQL injection (CWE-89)
- Недоверенный ввод склеивается или форматируется в текст SQL, поэтому кавычки, ключевые слова и операторы из ввода меняют структуру запроса вместо того, чтобы считаться одним значением.
- Prepared statement and bind parameters
- Запрос отправляется с плейсхолдерами (
?,$1,:name) и разбирается до прихода значений; значения передаются отдельно и всегда считаются данными. Это основная защита в любом драйвере и ORM. - Blind SQL injection
- Когда страница не показывает ни результатов, ни ошибок, атакующий извлекает данные по одному биту по различиям в ответе (булевы инъекции) или во времени ответа (временные). Отсутствие видимого вывода не означает отсутствие уязвимости.
- Second-order SQL injection
- Значение безопасно сохраняется, затем читается из вашей же базы и вклеивается в другой запрос. Параметризованным должен быть каждый запрос, включая те, что получают данные из ваших собственных таблиц.
- Identifiers and allowlists
- Плейсхолдеры переносят только значения, но не имена таблиц, столбцов или направление сортировки. Их нужно выбирать из фиксированного белого списка в коде и никогда не копировать из запроса.
Пошаговый сценарий атаки
Ввод попадает в запрос
Поле формы, параметр URL, заголовок или поле API передаётся коду, который строит оператор SQL.
Ввод вклеивается в текст SQL
Конкатенация, интерполяция или форматирование вставляют значение напрямую. Безобидное тестовое значение ' OR '1'='1 превращает WHERE name = '...' в всегда истинное условие.
База разбирает его как синтаксис
База получает одну строку, не может понять, какая часть пришла от пользователя, и выполняет изменённый оператор с правами приложения.
Данные читаются, меняются или удаляются
В зависимости от запроса и учётной записи атакующий обходит вход, выгружает таблицы запросами UNION или извлекает данные вслепую. Утечка MOVEit Transfer в 2023 году (CVE-2023-34362) началась именно с этого класса уязвимостей.
Руководства по SQL-инъекциям для каждого языка
Чек-лист по защите системы для инженеров
- Параметризуйте каждый запрос со значением, включая обходные пути сырого SQL в ORM, без исключений для внутренних или числовых входных данных.
- Выбирайте имена таблиц, столбцов и направления сортировки из жёстко заданных белых списков.
- Запускайте в CI правило SAST для SQL, собранного из строк (Bandit, gosec, Semgrep, CodeQL, Find Security Bugs, Brakeman или Psalm), и роняйте сборку на новых находках.
- Подключайтесь ролью БД с минимальными правами: без DDL, без суперпользователя, только нужные сервису таблицы.
- Считайте функции экранирования и правила WAF лишь дополнительными слоями: они пропускают контексты без кавычек и трюки с кодировками.
- Возвращайте клиентам общие сообщения об ошибках и пишите ошибки БД в серверный журнал, чтобы структура запроса никогда не раскрывалась.
Источники
- CWE-89: SQL-инъекция
- OWASP — руководство по предотвращению SQL-инъекций
- CISA — группировка CL0P эксплуатирует SQL-инъекцию в MOVEit