SQL Injection: Second-Order (хранимая инъекция)
Payload сохраняется в БД через безопасный INSERT, но выполняется в другом запросе через конкатенацию строк
hardgolang
Задача
# Second-Order SQL Injection (Хранимая инъекция через профиль)
## Сценарий
Вы проводите аудит безопасности **SecureShop**. Команда разработки гордится тем, что регистрация пользователей использует параметризованные запросы — простой `' OR 1=1 --` в поле `fullname` не приводит ни к ошибке, ни к компрометации БД. Однако автоматический сканер фиксирует подозрительные SQL-ошибки на странице профиля у некоторых пользователей с необычными именами. Похоже, разработчики защитили только точку записи, забыв про точку чтения.
## Цель
1. Зарегистрируйте нового пользователя со специально сформированным `fullname`, содержащим SQL-payload.
2. Найдите страницу, где сохранённые данные профиля попадают в SQL-запрос без параметризации.
3. Извлеките содержимое таблицы `secrets` через UNION-расширение payload'а.
4. Получите флаг — он хранится как значение ключа `admin_api_key`.
## Теория
**Second-Order SQL Injection** (она же «хранимая») — атака, при которой вредоносный payload не срабатывает в момент записи, а активируется позже — при чтении и использовании в другом SQL-запросе. Это особенно коварная разновидность: первый запрос (INSERT) выглядит безопасным даже под микроскопом, а вся уязвимость живёт в скрытом SELECT, выполняющемся на другом endpoint'е.
**Уязвимый паттерн:**
```go
// INSERT при регистрации параметризован — payload сохраняется как обычная строка:
h.db.Exec("INSERT INTO users (username, password, fullname) VALUES (?, ?, ?)", u, p, fullname)
// Но позже на /profile значение читается обратно и втыкается в SQL через fmt.Sprintf:
similarQuery := fmt.Sprintf(
"SELECT username, fullname FROM users WHERE fullname LIKE '%%%s%%' AND id != %d",
user.FullName, user.ID,
)
h.db.Query(similarQuery)
```
Сохранённое в БД `user.FullName` рассматривается как «доверенный внутренний источник», хотя по сути это всё тот же пользовательский ввод, только с задержкой во времени.
## Точка входа атаки
| Шаг | Метод | Путь | Описание |
|-----|-------|------|----------|
| 1 | `POST` | `/register` | Регистрация с payload в поле `fullname` |
| 2 | `POST` | `/login` | Вход под созданным пользователем |
| 3 | `GET` | `/profile` | Страница «People You May Know» — здесь срабатывает payload |
* **Обычный пользователь для разведки UI:** `demo` / `demo`
> Second-order SQLi — одна из самых сложных целей для автоматических сканеров: SQLMap и Burp Scanner тестируют связку input→output в одном запросе, а здесь точка входа и точка срабатывания разнесены.