SQL-ін’єкція — це метод отримання несанкціонованого доступу (різновид злому) до бази даних, при якому шкідливий код виконується прямо з поля вводу звичайної форми.
Якщо SQL-ін’єкція пройшла успішно, неавторизовані особи зможуть читати, створювати, оновлювати або навіть видаляти записи з таблиць бази даних. Цей метод використовується хакерами, пентестерами, тестувальниками тощо.
Приклад №1: SQL-ін’єкція з використанням декількох стейтментів
Припустимо, у нас на сайті є форма для пошуку товарів по ID. Фрагмент PHP-коду пошуку товару виглядатиме приблизно так:
|
1 2 3 |
$prod_id = $_GET["prod_id"]; $sql = "SELECT * FROM Products WHERE product_id = " . $prod_id; |
Якщо користувач введе значення 20, то SQL інтерпретує це як:
|
1 |
SELECT * FROM Products WHERE product_id = 20 |
Нічого підозрілого, правда?
Але якщо користувач введе 20; DROP TABLE Products;? Давайте подивимося, як SQL інтерпретує це:
|
1 |
SELECT * FROM Products WHERE product_id = 20; DROP TABLE Products; |
Ця команда видалить таблицю Products з бази даних. Це стало можливим, оскільки більшість систем управління базами даних (СУБД) можуть виконувати декілька команд одночасно.

Приклад №2: SQL-ін’єкція з використанням завжди істинної умови
Інший спосіб виконати SQL-ін’єкцію — це передати умову, результат якої завжди true, щоб дані завжди витягувалися, незважаючи ні на що.
Давайте поглянемо на інший фрагмент PHP-коду, де у нас є форма входу на наш веб-сайт, і користувачам потрібно вказати свій логін та пароль.
|
1 2 3 4 |
$username = $_POST["username"]; $password = $_POST["password"]; $sql = "SELECT * FROM Users WHERE username = \"" . $username . "\" AND password = \"" . $password . "\""; |
Якщо користувач введе логін як root і пароль як pass, то SQL інтерпретує це як:
|
1 |
SELECT * FROM Users WHERE username = "root" AND password = "pass" |
Цей фрагмент коду виглядає нормально, коли користувач вводить коректні дані.
Але що робити, якщо користувач введе ім’я користувача як invalid_user" OR "1"="1 і пароль як invalid_pass" OR "1"="1? Давайте подивимося, як SQL відреагує на це:
|
1 |
SELECT * FROM Users WHERE username = "invalid_user" OR "1"="1" AND password = "invalid_pass" OR "1"="1" |
Оскільки "1"="1" завжди true, незалежно від того, який логін та пароль введе користувач, SQL витягне всіх користувачів з бази даних.
Як захиститись від SQL-ін’єкцій?
Спосіб №1: Валідація користувацького вводу
Завжди слід перевіряти дані, які вводить користувач, перед їх фактичною відправкою до бази даних. Хорошими практиками є видалення пробілів, парсинг спеціальних символів, обмеження розміру вводу тощо.
Наприклад:
|
1 2 3 4 5 |
$data = $_POST["name"]; $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); |
Цей фрагмент PHP-коду певною мірою “перевіряє” вхідні дані.
Спосіб №2: Використання ORM
ORM (скор. від “Object Relational Mapping”) — це інструмент, який конвертує SQL-команди в код мови програмування та навпаки.
При використанні ORM здебільшого не потрібно писати “чистий” SQL-код. Оскільки ORM розроблені з урахуванням хороших практик та протоколів безпеки, вони надають захист, залишаючись при цьому простими у використанні.
Наприклад, наступний SQL-код:
|
1 |
SELECT * FROM Users WHERE id = 5; |
виглядатиме як
|
1 |
select(Users).where(Users.id == 5) |
в SQLAlchemy ORM для Python-кода.
Спосіб №3: Використання підготовлених запитів
Підготовлені запити — це SQL-код із плейсхолдерами. Передані аргументи просто розміщуються на місці плейсхолдерів.
Наприклад:
|
1 2 3 4 5 6 7 8 9 |
$sql = "INSERT INTO Users (first_name, last_name, email) VALUES (?, ?, ?)"; mysqli_stmt_bind_param($sql, "sss", $first_name, $last_name, $email); $first_name = "Harry"; $last_name = "Potter"; $email = "harrypotter@mail.com"; mysqli_stmt_execute($stmt); |
Тут передані значення поміщаються на місце ? та структура SQL-коду зберігається.
Висновки
SQL-ін’єкція — це дуже поширений спосіб злому. При використанні “сирого” SQL-коду, його слід ретельно протестувати та перевірити.
Ще одним альтернативним варіантом захисту при розробці програм/сайтів є використання фреймворків (таких як Django, Laravel, ASP.NET та ін.) замість того, щоб писати код з нуля. Фреймворки за замовчуванням обробляють SQL-ін’єкції, а також вирішують багато інших проблем.
