4. Извлечение полезной нагрузки
Извлечение полезной нагрузки: Пароли на экране
Разведка завершена, структура запроса ясна. Теперь хакер переходит к финальной стадии — извлечению реальных данных из секретных таблиц. Мы увидим, как простая замена 'a' на осмысленные запросы превращает страницу вашего интернет-магазина в панель управления учетными записями.
После двух предыдущих уроков (определение количества колонок и поиск текстового типа) у атакующего есть всё необходимое: знание схемы запроса и точки внедрения. Финальный шаг — подставить вместо placeholder'ов конкретные SELECT'ы к интересующим его таблицам. С точки зрения базы данных, это абсолютно валидный SQL: UNION-оператор объединяет два SELECT с одинаковым количеством колонок и совместимыми типами, и СУБД возвращает объединённый result set приложению.
Аналогия: представь, что вы заказываете каталог товаров по почте, и почтальон по ошибке вкладывает в конверт ещё и страницы из закрытого справочника личных данных клиентов. Получатель получает «один пакет» — листает каталог, и среди описаний айфонов вдруг видит реальные логины и пароли. Технически конверт цел, печать не сломана — но содержимое содержит то, чего не должно было там быть. UNION-инъекция работает ровно так же: ответ от сервера структурно валиден (HTTP 200, JSON массив товаров), но среди ожидаемых данных подмешаны украденные строки из другой таблицы.
Разберем, как именно происходит подмена данных и почему Go-сервер беспрекословно выводит их пользователю.
1. Механика: "Финальный удар"
Представьте уязвимый запрос в Go-коде:
SELECT id, name, price FROM products WHERE category = '%s' (через fmt.Sprintf).
Хакер уже знает, что в запросе 3 колонки, а вторая — текстовая. Он пишет:
category = 'Electronics' UNION SELECT 1, password, 3.14 FROM users--
Что произойдет в Go-хендлере:
// ❌ Go просто склеивает...
query := fmt.Sprintf("SELECT id, name, price FROM products WHERE category = 'Electronics' UNION SELECT 1, password, 3.14 FROM users--'")
rows, _ := db.Query(query)
// ...и выводит строки в цикле на страницу
ИТОГ: Вместо названия "iPhone", на сайте напротив каждого товара появится реальный пароль одного из пользователей вашего сайта!
Точнее, на сайте появится bcrypt-хеш пароля (если разработчик хотя бы это сделал правильно) или, в худшем случае, plaintext-пароль (если хранят пароли в открытом виде — что встречается чаще, чем хотелось бы в 2025 году). Атакующий копирует хеш и запускает hashcat с словарём из 10 миллионов паролей — для слабых паролей восстановление занимает минуты. Plaintext-пароли — это мгновенная компрометация всех учёток, плюс credential stuffing атаки на другие сервисы (LinkedIn, корпоративная почта, банк) через переиспользование паролей пользователями.
2. Популярные цели в SQL Injection
Хакеры ищут следующие данные в ваших таблицах:
| Цель | SQL-код (через UNION) | Описание |
|---|---|---|
| Версия БД | UNION SELECT 1, version(), 3-- |
Какой эксплойт использовать? |
| Имена таблиц | UNION SELECT 1, tablename, 3... |
Что еще есть интересного? |
| Логины | UNION SELECT 1, username, 3... |
Кто администратор? |
| Пароли | UNION SELECT 1, password, 3... |
Собственно, ключ от двери. |
3. Почему это фатальная уязвимость?
Причина — в доверии к данным. Ваш Go-код ожидает, что в name придут данные из таблицы products. Но из-за UNION база подсунула данные из users. Go-сервер ничего не заподозрил и просто вывел этот текст в браузер (или в JSON-ответ приложения).
Это пример более общей проблемы под названием type confusion: код ожидает данные одного типа/источника, но получает данные другого. Похожая ошибка лежит в основе многих CVE: десериализация неподписанных JSON в Java (CVE-2017-9805 Struts2), приведение типов в PHP == сравнении (Type Juggling), prototype pollution в JavaScript. Везде источник — отсутствие явной проверки того, что данные соответствуют ожидаемой структуре. В случае SQLi: Go ожидает строку названия продукта, но в эту строку попадает пароль другого пользователя — и сериализуется в JSON без проверки.
4. Как это выглядит в логах SQL (PostgreSQL)
Если вы посмотрите SELECT * FROM pg_stat_activity, вы увидите эту "химеру" — запрос к товарам, скрещенный с запросом к пользователям. Это 100% признак активного взлома.
В production-средах для мониторинга SQL-аномалий используют pgAudit (расширение PostgreSQL) или Percona Audit Plugin для MySQL — они логируют ВСЕ запросы с пользователем-инициатором и source IP. SIEM (Splunk, ELK, Datadog) собирает эти логи и применяет правила детекции: «алерт, если SELECT содержит UNION с таблицей не из ожидаемого списка», «алерт, если запрос к таблице users приходит с endpoint /api/products». Эти правила требуют tuning под конкретное приложение, но дают возможность поймать инъекцию в реальном времени.
Извлечение нагрузки — это момент, когда хакер наконец-то открывает ваш "банк данных". Вся конфиденциальная информация теперь находится в его руках.
Соответствие стандартам: OWASP Top 10 A03:2021 Injection; CWE-89 SQL Injection; PCI-DSS 6.5.1; GDPR Article 32 «Security of Processing» — эксфильтрация персональных данных через UNION-инъекцию по GDPR обязывает уведомить регулятора в течение 72 часов и пострадавших пользователей в разумные сроки, плюс гарантирует штраф до 4% годового оборота при доказанной халатности.
Известные инциденты с UNION-based SQLi: Heartland Payment Systems 2008 (134 миллиона карт через UNION-инъекцию в payment processor); TalkTalk 2015 (4 миллиона клиентов через UNION в legacy формe); Yahoo Voices 2012 (450 тысяч plaintext-паролей); Sony Pictures 2011 (миллион учётных записей). Каждый из этих инцидентов мог бы быть предотвращён одной строкой кода — заменой fmt.Sprintf на параметризованный запрос.
Но что, если текстовых колонок мало? Мы изучим, как хакеры обходят это ограничение с помощью функций объединения строк, таких как CONCAT.
Продолжить чтение
Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу
Когда закончишь — отметь раздел, чтобы продолжить.