5. Объединение значений (CONCAT)
Объединение значений (CONCAT): Склеивание ответов
Иногда в оригинальном запросе доступна всего одна текстовая колонка, а хакеру нужно вытащить сразу несколько полей — например, логин и пароль. Для этого используются функции конкатенации, которые позволяют "сжать" несколько данных в одну строку.
С точки зрения Go-разработчика паттерн знакомый — на бэкенде вы регулярно делаете fmt.Sprintf("%s:%s", login, pass) для формирования basic-auth токена. Атакующий проделывает ровно то же самое, но не на стороне приложения, а на стороне базы данных. Если ваш SELECT возвращает на фронт только одну колонку (например, name в JSON-ответе /api/products), атакующий «упаковывает» в эту единственную колонку весь интересующий его секрет — два, три, десять полей через разделитель.
Изучим синтаксис объединения в разных СУБД и поймем, почему разделители вроде двоеточия являются верным признаком атаки. Аналогия — посылка с двойным дном: на этикетке (структура JSON) написано «один документ», а внутри упаковано пять документов, склеенных скотчем, потому что курьер досматривает только размер посылки, не содержимое.
1. Механика: "Склеивание полей"
Представьте запрос в Go-коде:
SELECT id, name, price FROM products WHERE category = '%s' (через fmt.Sprintf).
Это стандартный паттерн интернет-магазина: страница /category/electronics рендерит список товаров через html/template, и каждый item-card показывает только name как текст, id уходит в data-id атрибут, price — в <span> форматирования. UI-разработчик не задумывается, что атакующий может через UNION SELECT подменить значение колонки name в трёх запросах подряд.
Хакер знает, что ему доступна только ОДНА текстовая колонка (name). Но он хочет вытащить сразу username и password из таблицы users. Решение — упаковать оба поля в одно: username || ':' || password в PostgreSQL даёт строку вида admin:5f4dcc3b5aa765d61d8327deb882cf99. Эта строка попадает в колонку name UNION-результата, и фронтенд аккуратно отрендерит её как название «товара» рядом с настоящими товарами магазина.
Разница в синтаксисе СУБД:
- PostgreSQL / SQLite:
username || ':' || password - MySQL:
CONCAT(username, ':', password)
2. Финальный удар хакера в Go
Хакер вводит в category:
' UNION SELECT 1, username || ':' || password, 3.14 FROM users--
Что произойдет в Go-хендлере:
// ❌ Go просто склеивает...
query := fmt.Sprintf("... UNION SELECT 1, username || ':' || password, 3.14 FROM users--'")
// ...и выводит строки в цикле на страницу
ИТОГ: Вместо названия "iPhone", на сайте появится строка: admin:mySuperSecretPassword123. Если пароли хранятся как bcrypt-хэши ($2a$10$...), атакующий получит хэши — а дальше offline brute force через hashcat на нескольких GPU. Yahoo Voices 2012: 450 тысяч паролей утекли именно так, через UNION с CONCAT — атакующие потом восстановили большинство по словарю.
3. Таблица работы: Исходный SQL vs CONCAT Атака
| Параметр | Исходный SQL | Результат атаки (SQL Injection) |
|---|---|---|
| Тип | name |
CONCAT(username, ':', password) |
| Количество | 1 поле | 2 поля в одном! |
| Статус | 🟢 БЕЗОПАСНО | 🔴 ВЗЛОМАНО |
4. Почему хакеры любят разделители? (Двоеточие)
Хакер добавляет : или другой редкий символ, чтобы потом в своем скрипте (или в браузере) легко разделить логин и пароль. Это "отпечаток" хакера, по которому вы легко можете опознать попытку взлома. Для SIEM/SOC это важный сигнал: если в access-логе nginx или в логах вашего Go-приложения мелькает строка вида ':admin:hash:role:, или сам пользовательский ввод содержит ||, CONCAT(, 0x3a (hex для :) — это почти всегда автоматизированный sqlmap-like инструмент.
Защита всё та же — параметризация. С db.Query("SELECT id, name, price FROM products WHERE category=?", category) ввод хакера ' UNION SELECT 1, username || ':' || password, 3.14 FROM users-- идёт в базу как литерал, и PostgreSQL/MySQL вернёт пустой результат — нет ни одного товара с таким category-именем. Никакого UNION в плане выполнения не появляется.
CONCAT — это способ для хакера уплотнить свою добычу. Когда данные не защищены, злоумышленник всегда найдет способ представить их в удобном для себя виде.
Теперь, когда мы изучили все методы нападения, пришло время поговорить о защите. Сравним использование «сырых» запросов с популярными Go-библиотеками и ORM.
Продолжить чтение
Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу
Когда закончишь — отметь раздел, чтобы продолжить.