Коротка відповідь
seniorSQL injection — це атака, коли зловмисник вставляє SQL‑код у вхідні дані, щоб змінити запит. Уникаємо її через параметризовані запити (prepared statements) і валідацію/санітизацію вводу. Також слід обмежувати права користувачів бази та використовувати ORM‑фреймворки, що автоматично підготовляють запити.
Повне пояснення
Що це і навіщо SQL injection – атака, при якій зловмисник вводить SQL‑код у поля вводу (наприклад, логін/пароль), що призводить до виконання небажаних запитів. Це дозволяє отримати доступ до даних, змінити їх або видалити.
Ключові принципи
- Параметризовані запити (prepared statements) – розділяють дані і команду.
- Валідація/санітизація вводу – перевірка типу, довжини, формату.
- Мінімізація прав – користувачі бази мають лише необхідні привілеї.
- Використання ORM – автоматичне підготовлення запитів, наприклад, Prisma, TypeORM.
Як це працює
При prepared statement сервер розпізнає параметри як дані, а не частину SQL‑коду. Якщо зловмисник вставить ' OR 1=1; --, це буде передано як рядок, а не виконаний код.
Практика й реалізація
-- PostgreSQL
PREPARE stmt AS SELECT * FROM users WHERE username = $1 AND password = $2;
EXECUTE stmt('admin', 'secret');
// Node.js з pg
const res = await client.query('SELECT * FROM users WHERE username=$1 AND password=$2', [user, pass]);
Тестування
- Unit: перевірка, що запит не змінюється при різних вхідних даних.
- Integration: використати бібліотеку
jest+supertest, щоб відправити payload з SQL‑кодом і перевірити, що результат не змінюється.
Оптимізація запитів
- Індекси на колонках, що часто фільтруються (username, email).
EXPLAINдля перевірки плану виконання.
Безпека
- SQL injection – одна з найпоширеніших вразливостей.
- Додаткові заходи: WAF, rate limiting, логування підозрілих запитів.
Особливості в контексті ORM
- Prisma:
await prisma.user.findUnique({ where: { email } })– автоматично підготовлений запит. - TypeORM:
repository.findOne({ where: { email } })– також використовує параметризовані запити.
Часті помилки
- Конкатенація рядків у SQL.
- Відсутність валідації типу даних.
- Надмірні привілеї користувача бази.
- Використання
evalабо подібних функцій. - Необхідність у підготовці запитів при використанні
LIKEз%. - Застарілі драйвери, що не підтримують prepared statements.
- Відсутність логування.
- Перевірка лише на рівні фронтенду, без бекенду.
Cheatsheet
?або$1, $2– placeholders.prepare,execute(PostgreSQL),stmt.execute()(MySQL).- ORM‑методи:
findUnique,create,update– всі підготовлені. - Перевірка:
SELECT 1 FROM dual WHERE 'x' = ?– простий тест.
Follow‑up питання
- Як працює
prepared statementу MySQL? - Чи можна уникнути SQL injection без ORM?