Что такое SQL-инъекция и как её используют злоумышленники
Основы3 минРедакция Innovialabs
Коротко
SQL-инъекция — уязвимость, при которой данные от пользователя становятся частью SQL-запроса и меняют его смысл. Через неё обходят вход, выгружают базу и удаляют данные; причина — склейка строк вместо параметризованных запросов.
Что такое SQL-инъекция
SQL-инъекция — уязвимость, при которой приложение собирает SQL-запрос из строк и вставляет в него ввод пользователя как есть. Злоумышленник подбирает такой ввод, чтобы он перестал быть «данными» и стал частью команды для базы.
База не знает, какую часть запроса написал программист, а какую — посетитель сайта. Она просто выполняет итоговый текст.
Как это выглядит
Типичный уязвимый код входа:
const sql = "SELECT * FROM users WHERE email = '" + email +
"' AND password_hash = '" + hash + "'";
Пользователь вводит в поле email:
admin@example.com' --
Запрос превращается в:
SELECT * FROM users WHERE email = 'admin@example.com' --' AND password_hash = '...'
Кавычка закрыла строку, а -- закомментировал проверку пароля. Злоумышленник вошёл как администратор, не зная пароля.
Другой классический ввод — ' OR '1'='1: условие становится истинным для всех строк таблицы.
Основные виды
| Вид | Как работает | Что видит атакующий |
|---|---|---|
| Классическая (in-band) | Результат или ошибка базы приходят прямо в ответе | Данные или текст ошибки SQL |
| UNION-based | К запросу добавляется UNION SELECT из другой таблицы | Чужие данные в обычном выводе страницы |
| Слепая по условию (boolean) | Атакующий задаёт вопросы «да/нет» | Разницу в ответе страницы |
| Слепая по времени (time-based) | Условие вызывает задержку ответа | Время ответа сервера |
UNION-инъекция
Страница товара берёт ID из адреса: /product?id=10. Если параметр вставляется в запрос напрямую, атакующий добавляет:
/product?id=10 UNION SELECT email, password_hash FROM users
Если число и типы колонок совпадают, вместо описания товара на странице окажутся email и хеши паролей.
Слепая инъекция
Иногда страница не показывает ни данных, ни ошибок. Тогда атакующий сравнивает ответы: id=10 AND 1=1 показывает товар, id=10 AND 1=2 — нет. Значит, условие выполняется. Задавая такие вопросы о символах в базе, можно вытащить данные по одному символу. Если и разницы в ответе нет, используют задержку: функции вроде SLEEP() в MySQL или pg_sleep() в PostgreSQL.
Слепые инъекции медленные, но их автоматизируют специальными инструментами, поэтому «у нас ничего не выводится» — не защита.
Какой ущерб она наносит
- Утечка данных: персональные данные клиентов, хеши паролей, заказы, переписка.
- Обход аутентификации: вход под любым пользователем, включая администратора.
- Изменение данных: смена цен, ролей, балансов.
- Удаление данных:
DELETEилиDROP TABLE, если драйвер разрешает несколько запросов подряд. - Доступ к серверу: при широких правах пользователя базы — чтение файлов, а в некоторых СУБД и выполнение команд ОС.
Кроме прямого ущерба, утечка персональных данных влечёт юридическую ответственность и потерю доверия.
Где искать уязвимые места
- Поиск, фильтры и сортировка в каталогах.
- Параметры в URL:
id,category,page. - Формы входа, регистрации и восстановления пароля.
- Заголовки и cookie, которые попадают в запросы (например, для логов или аналитики).
- Старые модули и «быстрые» скрипты для админки.
- Сырые запросы внутри ORM.
Частые заблуждения
- «Мы используем ORM, значит, защищены». Только пока не пишете сырые запросы с подстановкой строк.
- «Достаточно экранировать кавычки». Числовые параметры и имена колонок вставляются без кавычек, и экранирование не помогает.
- «Это внутренняя система». Внутренние пользователи и скомпрометированные аккаунты тоже атакуют.