EMZETT.
Увійти

SQLi (SQL-ін’єкція)

Коротко: Техніка атаки, за якої зловмисники вбудовують власний SQL-код у запит до бази даних через незахищені поля введення — може читати, змінювати або видаляти дані.

Докладніше: Виникає, коли введення користувача підставляється прямо в SQL-запит без перевірки (конкатенація рядків замість параметризованих запитів). Класичний приклад: у поле входу вводять ' OR '1'='1, і це може обійти перевірку пароля. Стандартний захист — параметризовані запити/підготовлені вирази, за яких введення користувача ніколи не інтерпретується як виконуваний SQL-код.

Подробиці

Вразливий запит входу може наївно виглядати так (конкатенація рядків, введення користувача вставлене прямо):

-- Вразливий код (НІКОЛИ так не пишіть):
query = "SELECT * FROM users WHERE username = '" + input + "' AND password = '" + pw + "'"
 
-- Введення: username = admin' --
-- Отриманий запит:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'
-- Перевірку пароля просто закоментовано за допомогою "--" (SQL-коментар)!

Такими маніпуляціями зловмисник може не лише обійти перевірку входу, а й залежно від прав підключення до бази даних читати цілі таблиці (UNION SELECT для підмішування даних з інших таблиць у вивід), змінювати чи видаляти дані, а в гірших випадках навіть виконувати команди на самому сервері бази даних.

Надійний захист структурний, а не «відфільтровування небезпечних символів»:

// Безпечно: параметризований запит - введення НІКОЛИ не інтерпретується як SQL-код
db.query("SELECT * FROM users WHERE username = $1", [input])

За параметризованих запитів (також «prepared statements») застосунок надсилає базі даних структуру запиту та введення користувача окремо — завдяки цьому база даних завжди знає, яка частина «код» (структура запиту), а яка — чисті «дані» (введення), що б користувач не вводив. Сучасні ORM (див. Drizzle ORM) за замовчуванням використовують усередині параметризовані запити, тому за правильного застосування ORM SQL-ін’єкція практично виключена — сирий SQL із конкатенацією рядків лишається можливим і небезпечним у будь-якій мові/фреймворку.

Сліпа SQL-ін’єкція

Вразливий застосунок не завжди прямо виводить помилки бази даних чи результати запитів — за «сліпої SQL-ін’єкції» зловмисник не бачить прямого зворотного зв’язку, але все ж може видобувати інформацію, формулюючи умови, що помітно впливають на поведінку застосунку (наприклад, інший час відповіді або інша сторінка залежно від того, чи істинна умова). Приклад: ' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a — якщо застосунок відповідає так само, як без умови, здогад вірний, інакше ні. Символ за символом таким способом теоретично можна видобути повний пароль, навіть без видимих повідомлень про помилки — значно повільніше за класичну SQLi, але не менш небезпечно.

Додаткові рівні захисту

Параметризовані запити — найважливіша, але не єдина лінія захисту. Принцип найменших привілеїв обмежує шкоду навіть від успішної ін’єкції: користувач бази даних, під яким підключається вебзастосунок, має мати лише справді потрібні права (наприклад, не мати права DROP TABLE для суто читального ендпоїнта). Брандмауер вебзастосунків (WAF) додатково може розпізнавати й блокувати відомі шаблони ін’єкцій у вхідному трафіку ще до того, як вони досягнуть застосунку — як додаткове страхування, а не заміна безпечного доступу до бази даних у самому коді. Регулярні автоматичні сканування безпеки (наприклад, інструментами на кшталт sqlmap у межах власних тестів) допомагають рано знаходити випадково внесені діри ін’єкцій, перш ніж це зробить реальна атака.

Див. також: SQL, Підроблені cookie