Воспроизведи SQL-инъекцию, обезвредь её подготовленными запросами и примени принцип наименьших привилегий.
Открыть этот урок в KodokonSQL-инъекция возникает в тот момент, когда недоверенные данные склеиваются с текстом запроса. Атакующий подаёт значение, которое закрывает строку и перехватывает логику. Воспроизведём атаку на таблице users: прямая склейка со вводом ada' OR '1'='1 превращает точный фильтр во всегда истинное условие.
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
is_admin INTEGER NOT NULL DEFAULT 0
);
INSERT INTO users (id, name, is_admin)
VALUES (1, 'ada', 0), (2, 'root', 1);
-- Dangerous concatenation (NEVER do this)
-- input = ada' OR '1'='1
SELECT * FROM users
WHERE name = 'ada' OR '1'='1';Полезная нагрузка срабатывает, потому что кавычка преждевременно закрывает литерал 'ada', а затем OR '1'='1' добавляет универсально истинное условие. Вариант этой атаки дописывает --, чтобы закомментировать остаток исходного запроса. Вывод: пока данные и код живут в одной строке, никакое ручное экранирование по-настоящему не надёжно.
-- Positional placeholder
SELECT * FROM users WHERE name = ?;
-- Named placeholder
SELECT * FROM users WHERE name = :name;Лекарство - подготовленный запрос: драйвер сначала компилирует структуру запроса, а потом связывает значения отдельно. Связанные данные никогда не разбираются как SQL, они только сравниваются. Бонусом скомпилированная структура переиспользуется: связывая значения одно за другим, ты не перекомпилируешь план при каждом вызове.
-- The bound value stays data, not SQL
SELECT * FROM users
WHERE name = :name;
-- :name = ada' OR '1'='1
-- -> 0 rows: no user
-- is literally named that' OR '1'='1 успешно внедряется, потому что она...??:name