SQL-инъекция остаётся одной из самых опасных и при этом самых примитивных уязвимостей в веб-разработке. Она не требует «магии» — только неосторожной строки кода, где пользовательский ввод напрямую попадает в SQL-запрос. Последствия могут варьироваться от утечки данных до полного уничтожения базы.
Несмотря на развитие фреймворков и ORM, проблема не исчезла. Причина проста: скорость разработки выросла, особенно с приходом ИИ. Модели генерируют код быстро, но без явных требований к безопасности они легко создают уязвимые конструкции.
В этом материале разберём, как именно работают SQL-инъекции, какие существуют типы атак, как их обнаруживают на практике и, главное, как выстроить систему, при которой даже сгенерированный ИИ код будет изначально безопасным.
1. Что такое SQL-инъекция (простыми словами)
Представь: ты пишешь запрос к базе:
SELECT * FROM users WHERE login = 'введённый_логин';
Пользователь вместо логина вводит:
admin' OR '1'='1
Запрос превращается в:
SELECT * FROM users WHERE login = 'admin' OR '1'='1';
База отдаёт ВСЕХ пользователей. Добро пожаловать в классическую SQL-инъекцию.
Это не баг базы данных. Это баг твоего кода, который позволил пользователю «вмешаться» в SQL-запрос.
Реальные последствия:
- Утечка миллионов паролей (вспомни Yahoo, LinkedIn, Sony).
- Полное удаление таблиц (DROP TABLE users).
- Чтение файлов сервера (LOAD_FILE('/etc/passwd')).
- Захват сервера через xp_cmdshell (в старых MSSQL).
Даже в 2026 году OWASP ставит Injection на 1-е место в Top 10.
2. Как это выглядит на практике (примеры уязвимого кода)
Плохой код:
Python + psycopg2
# ❌ ОПАСНО!
query = f"SELECT * FROM users WHERE email = '{user_email}'"
cur.execute(query)
Node.js
// ❌ ОПАСНО!
const query = `SELECT * FROM bots WHERE token = '${token}'`;
PHP
// ❌ Классика 2010-х
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
Хакер в поле «email» пишет: ' OR '1'='1 — и готово.
3. Виды SQL-инъекций
- Classic (Error-based) — база ругается ошибкой и выдаёт данные.
- Union-based — UNION SELECT password FROM users (самая популярная).
- Blind (Boolean/Time-based) — запросы типа AND (SELECT 1)=1 или AND SLEEP(5).
- Out-of-band — данные уходят на сервер хакера через DNS.
- Second-order — инъекция срабатывает позже (например, при сохранении в базу и последующем чтении).
4. Как хакеры находят уязвимость
Самый популярный инструмент — sqlmap.
Промт для ИИ (чтобы он сам настроил тебе sqlmap):
Напиши пошаговый план установки и запуска sqlmap против моего тестового эндпоинта /login?email= на локалхосте. Используй --risk=3 --level=5 --batch. Покажи команду для теста формы логина.
Запусти — и увидишь красные строки «[CRITICAL] parameter 'email' is vulnerable».
5. Главная защита: Параметризованные запросы (Prepared Statements)
Это единственный 100% способ закрыть SQL-инъекции на уровне кода.
Как это работает: База сначала получает «шаблон» запроса, потом отдельно — данные. Данные никогда не становятся кодом.
6. Готовые решения
Вариант А — ORM (рекомендую для новичков)
- Prisma (Node.js / TypeScript) — просто мечта.
- SQLAlchemy 2.0 (Python) — с async.
- Drizzle ORM (TypeScript) — лёгкий и быстрый.
- GORM (Go) — если вдруг.
Промт для Claude/GPT (универсальный):
Напиши полный код авторизации пользователя в Telegram-боте на Python + aiogram 3 + SQLAlchemy 2.0 + asyncpg (PostgreSQL/Supabase).
Обязательно используй parameterized queries (не f-строки!).
Добавь валидацию email через Pydantic.
Добавь rate-limit 5 попыток в минуту.
Сделай код максимально безопасным и с комментариями для новичка.
Вариант Б — ручные prepared statements
Python + psycopg2 (Supabase)
cur.execute(
"SELECT * FROM users WHERE email = %s AND password = %s",
(email, hashed_password)
)
Node.js + pg
const { rows } = await pool.query(
'SELECT * FROM users WHERE email = $1',
[email]
);
PHP + PDO
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
7. Дополнительные уровни защиты (defense in depth)
- Валидация и санитизация вводаРегулярки + whitelist.
Zod / Pydantic / Joi. - Принцип наименьших привилегийСоздай отдельного пользователя базы ТОЛЬКО с правами SELECT/INSERT/UPDATE на нужные таблицы.
Никогда не используй postgres или root в приложении. - Web Application Firewall (WAF)Cloudflare WAF (бесплатно до 100к запросов).
ModSecurity + OWASP CRS.
Supabase имеет встроенную защиту. - Хранимые процедуры (с параметрами!)
- ORM + Prepared Statements = почти невозможно ошибиться.
8. Как просить ИИ писать безопасный код
Универсальный промт-шаблон:
Напиши код для [функция, например: регистрация пользователя].
Обязательные требования:
- Использовать ТОЛЬКО parameterized queries / ORM
- Никогда не конкатенировать строки в SQL
- Валидация через [Zod/Pydantic]
- Rate limiting
- Хэширование паролей через bcrypt/argon2
- Комментарии "// SECURITY:" для каждой защитной меры
- Защита от SQLi, XSS, CSRF
9. Чек-лист перед деплоем
- Все SQL-запросы параметризованы?
- Пользователь БД имеет минимальные права?
- Валидация + санитизация на всех входах?
- Запущен sqlmap-тест?
- WAF включён?
- Логирование подозрительных запросов?
- Регулярные обновления зависимостей (npm audit, pip-audit)?
10. Что делать, если уже взломали
- Отключи приложение.
- Смени все пароли и токены.
- Восстанови из чистого бэкапа.
- Проведи аудит кода.
- Добавь все защиты выше.
- Сообщи пользователям (по закону).
Заключение
SQL-инъекция — это не «сложная хакерская штука». Это ошибка, которую можно закрыть одной правильной строчкой кода.
Сейчас, в эпоху ИИ, ты можешь писать код быстрее всех — но только если научишь ИИ писать безопасно.