сеньорчикОткрыть в Telegram
← блог
21 июля 2026 г.

SQL-инъекция: как работает и как от неё защищаться

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

Разберём механику и защиту.

Как это работает

Приложение собирает запрос из строк, подставляя туда пользовательский ввод:

query = "SELECT * FROM users WHERE email = '" + email + "'"

Пользователь вводит обычную почту, и всё в порядке. Но если он введёт строку с кавычкой и своим куском SQL, она попадёт прямо в текст запроса и станет его частью.

База не различает, где ваш код, а где данные: она получает одну строку и выполняет её целиком. Именно в этом суть уязвимости, а не в конкретных символах.

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

Почему до сих пор встречается

Уязвимый код проще написать. Строку склеить быстрее, чем разбираться с параметрами, особенно когда запрос собирается динамически из условий.

Плюс типичные места, где защита забывается:

Динамическая сортировка: имя колонки в ORDER BY нельзя передать параметром, и разработчик подставляет его строкой.

Поиск с LIKE, где к вводу добавляются проценты.

Списки идентификаторов в IN, которые собираются склейкой.

Запросы в отчётах и админках, которые «внутренние, туда никто чужой не зайдёт».

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

Правильная защита

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

cursor.execute("SELECT * FROM users WHERE email = %s", (email,))

Разница с первым примером в одну запятую, а по смыслу принципиальная.

ORM. Современные ORM по умолчанию используют параметры, поэтому обычный код через них безопасен. Но дыра появляется там, где вы вставляете сырой SQL, а такие места есть почти в каждом проекте.

Белые списки там, где параметры невозможны. Для сортировки и имён таблиц параметр не подходит, поэтому проверяйте значение по заранее известному списку допустимых. Не экранируйте, а сверяйте с перечнем.

Права доступа. Приложение не должно ходить в базу под суперпользователем. Отдельная роль с минимальными правами превращает потенциальную катастрофу в неприятность.

Чего делать не надо: писать свою функцию экранирования кавычек. Кодировки, юникод и особенности диалектов делают этот путь минным полем, а выигрыш нулевой.

Слепые инъекции

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

Атакующий задаёт базе вопросы вида «первый символ пароля больше M?» и по времени ответа читает данные посимвольно. Медленно, но работает, а автоматические инструменты делают это за минуты.

Практический вывод: отсутствие видимой ошибки не означает защищённость. Сообщения об ошибках прятать надо, но это не защита от инъекции, а гигиена.

Как проверить свой проект

Поиск по кодовой базе на конкатенацию строк рядом с SQL. Обычно находится быстро.

Проверка мест с сырыми запросами в ORM.

Просмотр всего, что собирается динамически: фильтры, сортировки, отчёты.

Тестовые запросы с кавычкой в каждом поле ввода. Примитивно, но неожиданно результативно.

Статический анализатор в пайплайне: большинство ловит очевидные случаи.

Что спрашивают на собеседовании

Что такое SQL-инъекция и как от неё защититься. Почему параметризованные запросы безопасны. Достаточно ли ORM. Что делать с динамической сортировкой. Почему нельзя просто экранировать кавычки.

Дальше обычно расширяют на общую безопасность: XSS, CSRF, хранение паролей, работа с секретами. Для бэкендера и тестировщика это стандартный блок, и на нём часто сыпятся, потому что готовятся к алгоритмам, а не к этому.

Про то, как устроены запросы в целом, писали в статье о реляционных базах данных, а про интерфейсы приложения в разборе что такое API.

Коротко

Не склеивайте SQL из строк. Используйте параметры. Для имён колонок применяйте белые списки. Ограничивайте права пользователя базы. Не пишите своё экранирование.

Пять правил, и целый класс уязвимостей закрыт.

Проверить, что тема уложилась, можно вопросами: в Сеньорчике есть блок по веб-безопасности в треках бэкенда и тестирования, с разбором каждого вопроса. Движок возвращает темы, где вы ошибаетесь. Десять минут в день в Telegram, бесплатно.