Перейти к содержимому
← Каталог golang Auth Bypass

Небезопасный Сброс Пароля (IDOR)

Форма сброса пароля принимает user_id из клиента, позволяя атакующему сбросить пароль любого пользователя через IDOR.

mediumgolangPro
Задача
# Auth: захват аккаунта через небезопасный сброс пароля (IDOR) ## Сценарий Вы аудируете интернет-магазин **SecureShop**. У приложения есть стандартный workflow восстановления пароля: пользователь вводит логин на странице «Forgot Password», получает email с одноразовым ссылкой-токеном, переходит по ней и устанавливает новый пароль. Команда уверена, что workflow безопасен — токен генерируется случайно, проверяется на существование, удаляется после использования. По данным внутреннего аудита, в админ-панели хранится конфиденциальная метка, доступная только admin-учётке; её требуется получить, имея только обычную учётную запись. ## Цель 1. Изучите параметры финального POST-запроса подтверждения сброса пароля: какие поля передаются с клиента, какие из них контролирует пользователь, какие проверяются сервером. 2. Найдите параметр, который сервер принимает «как есть», без серверной валидации соответствия другим полям — параметр, через который атакующий мог бы повлиять на ход исполнения. 3. Используя обнаруженный канал, захватите admin-аккаунт и извлеките флаг из админ-панели. ## Теория Workflow сброса пароля через email-токен — стандартный паттерн в современных приложениях, и он же — частый источник IDOR-уязвимостей. Корректная реализация хранит **серверную связь** между токеном и идентификатором пользователя (либо в БД через `reset_tokens(token, user_id)`, либо в самом токене через криптоподпись HMAC) и при подтверждении сброса извлекает `user_id` **исключительно из этой серверной связи**. Уязвимая реализация — частая ошибка — принимает `user_id` (или email, или username) **из тела POST-запроса** клиента, считая, что «пользователь же только что заполнил форму, как ещё его идентифицировать». **Уязвимый паттерн:** ```go // Сервер доверяет user_id из тела клиентского запроса при сбросе пароля token := r.FormValue("token") userID := r.FormValue("user_id") // <-- контролируется атакующим newPassword := r.FormValue("new_password") db.Exec("SELECT 1 FROM reset_tokens WHERE token=?", token) // проверка существования токена db.Exec("UPDATE users SET password=? WHERE id=?", newPassword, userID) // на любого user_id! ``` Атака предельно проста: атакующий запрашивает сброс пароля **для своего собственного** аккаунта, получает валидный токен, открывает форму подтверждения, изменяет hidden-поле `user_id` (или эквивалент в JSON-теле) на ID администратора, и отправляет форму с новым паролем. Сервер «принимает» токен (он валиден — для аккаунта атакующего), но обновляет пароль уже у admin-учётки. ## Точка входа атаки | Параметр | Значение | |----------|----------| | Учётные данные | `demo` / `demo` | | Запрос сброса | `POST /forgot-password` | | Подтверждение сброса | `POST /reset` (форма с `token`, `user_id`, `new_password`) | | Встроенный почтовый ящик (для своих писем) | `/email` | | Привилегированный эндпоинт | `GET /admin` |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru