3. Роль комментариев
Использование SQL-комментариев
Комментарии в SQL — это не только способ оставить заметку коллеге, но и мощный инструмент для завершения инъекции. С их помощью хакер «отрезает» всё, что идет после его вредоносного кода, предотвращая синтаксические ошибки базы данных.
Для Go-разработчика этот трюк особенно болезнен в multi-condition login-запросах: вы пишете SELECT id FROM users WHERE username='X' AND password_hash='Y' через fmt.Sprintf, ожидая что обе колонки проверятся. Атакующий вводит admin'-- в username — и базе достаётся WHERE username='admin' AND password_hash='...' с условием AND password_hash='...' внутри комментария. Сравнение пароля просто не происходит. Это самый дешёвый exploit-payload в истории SQLi — 8 символов.
Посмотрим на разные стили комментариев и как они помогают сделать атаку незаметной для парсера. Аналогия — заявление в банке: вы заполнили графу «Имя» и «ФИО», а ниже стоит «Кодовое слово». Если злоумышленник в графу «Имя» напишет Сергей. ИГНОРИРОВАТЬ ВСЁ НИЖЕ, а охранник банка следует инструкции дословно — кодовое слово проверяться не будет.
1. Механика: "Обрезание" кода
Представьте типичный запрос из Go-хендлера:
SELECT id FROM users WHERE username='%s' AND password='%s' (через fmt.Sprintf).
Этот код встречается в каждом втором туториале «Go login example» на Хабре или Medium — и каждый второй разбор такого туториала забывает упомянуть параметризацию. В результате паттерн расходится по pet-проектам и MVP-стартапам без какой-либо проверки безопасности.
Хакер вводит в поле username: admin' --.
Как это видит SQL-парсер:
SELECT id FROM users WHERE username='admin' --' AND password='...'
Все, что идет после двух тире (--), база данных считает обычным комментарием и НЕ ВЫПОЛНЯЕТ.
- Оригинальный запрос:
WHERE username='admin' AND password='...' - Результат атаки:
WHERE username='admin'
Поздравляем: вы только что авторизовали хакера в аккаунт администратора без пароля! Это классический auth-bypass — payload известен с конца 1990-х и до сих пор регулярно срабатывает на CTF и в реальных bug bounty. На HackerOne такие отчёты до сих пор уходят за 5000-10000 USD, потому что компании сами не верят, что в 2026 году у них может быть такой банальный баг.
2. Разновидности комментариев в разных СУБД
Хакеры знают, какая база данных установлена на вашем сервере, и используют соответствующие символы. Для них это часть фингерпринтинга: если admin'-- не работает, но работает admin'#, то это MySQL. Если работает admin'/* без закрывающего */ — это MSSQL в режиме «терпимости к незакрытым комментариям».
| СУБД | Однострочный комментарий | Многострочный |
|---|---|---|
| PostgreSQL | -- (пробел необязателен) |
/* */ |
| MySQL | # или -- (пробел ОБЯЗАТЕЛЕН) |
/* */ |
| SQLite | -- |
/* */ |
| MS SQL Server | -- |
/* */ |
3. Таблица работы: Исходный SQL vs Атака
| Параметр | Исходный SQL | Результат атаки (SQL Injection) |
|---|---|---|
| Тип | user='%s' AND pass='%s' |
user='admin' -- ' AND pass='...' |
| Условие | Логин И Пароль | ТОЛЬКО ЛОГИН |
| Статус | 🟢 БЕЗОПАСНО | 🔴 ВЗЛОМАНО |
4. Почему это работает в Go?
Потому что Go-пакет fmt.Sprintf просто "склеивает" текст, не понимая его значения. Для Go строка — это просто массив байтов. Для базы данных — это команда. Различие в восприятии — это и есть уязвимость. На уровне типов Go не делает различия между «безопасной строкой» и «недоверенным вводом» — оба типа string. Линтер go vet это тоже не отлавливает. Защитники типов появляются только в специализированных linter-ах вроде gosec (правило G201), но они не включены в стандартный go vet и часто отсутствуют в CI молодых проектов.
Решение: db.QueryRow("SELECT id FROM users WHERE username=? AND password_hash=?", u, hashFn(p)).Scan(&id). Драйвер database/sql отправляет SQL-команду и значения параметров отдельно — по wire-protocol. PostgreSQL/MySQL получает WHERE username=$1 AND password_hash=$2 как структуру AST, а admin'-- — как литеральное значение $1. Никакого «парсинга» ввода нет, потому что ввод не доходит до парсера SQL.
Отрезая лишнее, хакер гарантирует, что база выполнит именно его команду. Это делает инъекцию компактной и работоспособной.
Пришло время перейти от изучения атак к защите. Начнем с самого важного инструмента — подготовленных выражений.
Продолжить чтение
Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу
Когда закончишь — отметь раздел, чтобы продолжить.