SQL-инъекции: как работают и как от них защититься
Разбираем одну из самых известных уязвимостей веба на живом примере: почему склейка строк опасна и почему подготовленные запросы решают проблему полностью.
SQL-инъекция возникает, когда данные пользователя попадают прямо в текст SQL-запроса. Тогда пользователь может не просто передать значение, а дописать в запрос свой код.
Пример уязвимого кода
Допустим, сайт ищет пользователя по имени так:
query = "SELECT * FROM users WHERE name = '" + name + "'"
db.execute(query)Если в поле ввести alice, получится нормальный запрос. А если ввести ' OR '1'='1, запрос превратится в:
SELECT * FROM users WHERE name = '' OR '1'='1'Условие '1'='1' всегда истинно — база вернёт всех пользователей. Так обходят проверку пароля, читают чужие данные, а иногда и удаляют таблицы.
Слепая инъекция
Бывает, что сайт не показывает результат запроса, а только отвечает «да» или «нет». Атакующий всё равно может вытащить данные по одному символу, задавая вопросы вроде «первая буква пароля больше M?». Это называется слепой SQL-инъекцией — разобраться в ней на практике можно в задаче Слепая инъекция в логах.
Как защититься
Единственный надёжный способ — подготовленные запросы (параметризованные запросы). Текст запроса и данные передаются в базу отдельно, и данные никогда не становятся кодом:
db.execute("SELECT * FROM users WHERE name = ?", (name,))Что не работает как защита:
- Ручное экранирование кавычек — легко забыть один случай или кодировку.
- «Чёрные списки» слов вроде
ORиDROP— их обходят регистром, комментариями и пробелами. - Проверка только на клиенте в JavaScript — запрос можно отправить в обход браузера.
Дополнительно стоит давать приложению учётную запись базы с минимальными правами: тогда даже успешная инъекция не сможет удалить таблицы.
Попробуйте сами
Посмотрите комнаты категории Веб, а писать безопасный код учит категория «Защита» — например, экранирование HTML.