3. Анатомия успешной атаки
Анатомия успешной атаки: Глазами SQL-парсера
Как именно хакер превращает обычный поиск товара в кражу всей базы данных? Ключ к пониманию лежит в структуре самого SQL-запроса. Используя специальные символы (кавычки, комментарии) и логические операторы, взломщик буквально «дописывает» вашу программу на лету.
Аналогия из реальной жизни: представь, что вы пишете текст контракта на бумажной форме, где для каждого поля выделено место. Поле «Получатель: ___», поле «Сумма: ___», поле «Назначение: ___». Если в поле «Получатель» можно вписать сколь угодно длинный текст без разделителей, то хитрый клиент впишет туда: «Иван Иванов, а также прошу провести второй перевод на $1000000 на счёт 12345». Когда бухгалтер обрабатывает контракт, он не видит границ полей — просто читает текст слева направо и выполняет все указания. SQL-инъекция работает ровно так же: атакующий «выходит за границы» поля username с помощью кавычки и комментария, и добавляет свои инструкции в сам текст SQL-запроса.
Разберем по шагам, как конструируется классическая полезная нагрузка и почему база данных послушно её исполняет.
Как это выглядит пошагово
Представьте эндпоинт Go для входа в систему. Он берет username и password, формирует строку через fmt.Sprintf и отправляет в базу:
// ❌ УЯЗВИМО: Конкатенация
query := fmt.Sprintf("SELECT id FROM users WHERE user='%s' AND pass='%s'", u, p)
Шаг 1: Нормальная работа (Ничего особенного)
- Пользователь вводит:
user=admin,pass=12345 - Переменная
queryв Go:SELECT id FROM users WHERE user='admin' AND pass='12345' - SQL-парсер видит два условия (username и password) и возвращает ID, если они совпали.
Шаг 2: Ввод хакера (Начало атаки)
- Хакер вводит в поле
user:admin' --(админ, кавычка, пробел, два тире). - Хакер вводит в поле
pass:чего-нибудь.
Шаг 3: Момент «склеивания» в Go
Переменная query теперь выглядит так:
SELECT id FROM users WHERE user='admin' --' AND pass='чего-нибудь'
Обрати внимание на момент «склеивания» — это критическая точка. Go-runtime не делает никакой магической проверки безопасности. Функция fmt.Sprintf это обычная string formatter, как printf в C — она просто подставляет аргументы в шаблон. Нет никакого «сигнала из БД», что часть строки опасна. Уязвимость рождается в этой бесхитростной операции подстановки, и существует от момента её выполнения до отправки в базу. Дальше уже поздно — SQL-парсер базы получает готовую строку и просто исполняет.
Почему это сработало? (Роль кавычек и комментариев)
Разберем, как SQL-парсер разбирает эту строку:
| Часть запроса | Что видит парсер? | Описание |
|---|---|---|
SELECT id FROM users |
Команда | Нужно достать данные |
WHERE user='admin' |
Условие 1 | Найти пользователя 'admin' |
' |
Закрытие данных | Хакер закрыл строку сам! |
-- |
Комментарий | ВСЁ ЧТО ДАЛЬШЕ — СМУСЛИ! |
' AND pass=... |
Мусор | Эти условия база проигнорирует |
Визуализация: Исходный SQL vs Модифицированный
Хакер "обрезал" кусок вашего запроса прямо посреди выполнения. Теперь база данных выполнит только:
SELECT id FROM users WHERE user='admin'
РЕЗУЛЬТАТ: АВТОРИЗАЦИЯ ВЫПОЛНЕНА БЕЗ ПАРОЛЯ. Вы только что пропустили хакера в аккаунт администратора.
Это authentication bypass — один из самых частых сценариев SQLi в реальных инцидентах. По данным OWASP, около 60% успешных SQL-инъекций в production-системах используются именно для обхода аутентификации, а не для извлечения данных. Логика проста: получив админский аккаунт, атакующий уже легитимно делает всё остальное через UI, не оставляя следов SQL-инъекции в логах. Это идеальное «прикрытие» для дальнейших действий.
Самые популярные символы атаки
Никогда не забывайте про эту троицу:
'(одиночная кавычка) — выход за границы строковых данных.--(два тире и пробел) — комментарий в PostgreSQL/MySQL (все после этого игнорируется).#(решетка) — комментарий в MySQL.
Дополнительные spec-символы: /* ... */ (block comment, работает во всех СУБД); ; (statement terminator — позволяет начать новый SQL-запрос внутри текущего); \x00 (null-byte — в некоторых старых драйверах обрывает строку); двойная кавычка " (в PostgreSQL — кавычка identifier, в MySQL — может быть строкой в зависимости от sql_mode). Понимание этих символов критично для написания payload, а для defender'а — для понимания, что blacklist-фильтр всегда что-нибудь упускает.
Каждый символ в payload имеет значение: кавычка закрывает данные, операторы меняют логику, а комментарии прячут остатки оригинального кода. Это делает атаку хирургически точной.
Defence: одна замена db.Query(fmt.Sprintf(...)) на db.Query("SELECT ... WHERE user = ? AND pass = ?", u, p) закрывает уязвимость полностью. Драйвер базы передаст параметры через bind-механизм, и любые кавычки/комментарии в значениях останутся внутри значений, не достигая парсера. Эта одна строка кода — разница между уязвимым и безопасным приложением. Соответствие стандартам: CWE-89 SQL Injection; OWASP Top 10 A03:2021; PCI-DSS 6.5.1.
Зная, как выглядит атака изнутри, мы можем оценить масштаб последствий, которые она несет для бизнеса и пользователей.
Продолжить чтение
Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу
Когда закончишь — отметь раздел, чтобы продолжить.