Forced Browsing: доступ к скрытому эндпоинту экспорта
Административный эндпоинт /admin/export зарегистрирован без проверки роли — любой авторизованный пользователь может получить CSV-экспорт с конфиденциальными данными.
easygolangPro
Задача
# Forced Browsing: незащищённый административный эндпоинт
## Сценарий
Вы зарегистрированный пользователь интернет-магазина **SecureShop**. У приложения есть админ-панель `/admin`, доступная только администраторам — её защита работает корректно. Команда добавляла новые admin-фичи постепенно, и в течение нескольких релизов появились дополнительные административные эндпоинты для экспорта данных, статистики, операций над пользователями. Команда уверена, что **все** административные маршруты защищены одинаково. По данным внутреннего аудита, среди этих маршрутов есть один, который выгружает конфиденциальные данные системы (включая секретные токены); его требуется обнаружить и извлечь флаг.
## Цель
1. Изучите структуру административных эндпоинтов: какие пути зарегистрированы под `/admin`, и какие именно проверки применяются к каждому из них.
2. Найдите административный эндпоинт, который зарегистрирован с менее строгой проверкой доступа, чем другие — типичная ошибка при добавлении новых маршрутов.
3. Используя обычную учётную запись, обратитесь к этому эндпоинту и извлеките флаг из его ответа.
## Теория
Forced Browsing (или Direct Request, CWE-425) — класс уязвимостей, при которых атакующий получает доступ к закрытому функционалу через прямой URL-запрос, минуя UI-навигацию. Уязвимость возникает, когда защита реализована на уровне UI (страница не показывает ссылку на админ-функцию обычному пользователю) или на части маршрутов, но **не на всех** административных эндпоинтах. Современный пример — CVE-2023-42793 в JetBrains TeamCity: один из административных эндпоинтов был зарегистрирован без проверки аутентификации, что позволило RCE на любом инстансе.
**Уязвимый паттерн:**
```go
// Часть маршрутов защищена admin-middleware, часть — только auth-middleware
mux.HandleFunc("GET /admin", h.AdminMiddleware(h.AdminPanel))
mux.HandleFunc("POST /admin/delete", h.AdminMiddleware(h.AdminDelete))
mux.HandleFunc("GET /admin/export", h.AuthMiddleware(h.AdminExport)) // <-- забыли AdminMiddleware
```
С точки зрения архитектуры: разные категории маршрутов должны быть **сгруппированы** под одну middleware-цепочку, а не регистрироваться по одному с риском «забыть» правильную защиту. Атакующему достаточно проверить набор стандартных admin-путей (`/admin/export`, `/admin/users`, `/admin/api`, `/admin/debug`) с обычной валидной сессией — один из них может быть незащищён.
## Точка входа атаки
| Параметр | Значение |
|----------|----------|
| Учётные данные обычного пользователя | `demo` / `demo` |
| Защищённая админ-страница | `GET /admin` (требует admin-роли) |
| Цель | обнаружить административный эндпоинт без admin-проверки и извлечь флаг из его ответа |