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

Timing Attack: Перечисление Пользователей

Обработчик логина имеет разное время ответа для существующих и несуществующих пользователей, что позволяет перечислять аккаунты.

hardgolangPro
Задача
# Timing Attack: перечисление пользователей через различия во времени ответа ## Сценарий Вы аудируете интернет-магазин **SecureShop**. У приложения есть форма логина с корректным сообщением об ошибке при неверных данных: «Invalid credentials» — одинаковый текст для несуществующего пользователя и для существующего с неверным паролем. Команда уверена, что защита от user enumeration реализована — атакующий не может по сообщению понять, существует ли учётка. По данным внутреннего аудита, в админ-панели хранится конфиденциальная метка, доступная пользователю с привилегиями admin; её требуется получить. ## Цель 1. Изучите поведение эндпоинта логина для разных сценариев: несуществующий пользователь, существующий с неверным паролем, существующий с верным паролем. Сравните не только текст ответа, но и поведение по другим осям (время, заголовки, статус). 2. Найдите боковой канал утечки информации, через который можно различить «несуществующий пользователь» от «существующий с неверным паролем» — даже при идентичном текстовом ответе. 3. Используя этот канал, подтвердите наличие admin-учётки и получите доступ к админ-панели; извлеките флаг. ## Теория User enumeration через **timing side-channel** — класс уязвимостей, при которых атакующий определяет существование учётной записи по различиям в **физическом времени обработки** запроса, даже если все наблюдаемые ответы (статус, заголовки, тело) идентичны. Корень проблемы — в том, что путь обработки запроса проходит через дорогостоящие операции (хеширование пароля, обращение к БД, проверка криптоподписи) **только когда пользователь существует**; если кода нет — обработка завершается мгновенно. **Уязвимый паттерн:** ```go // Дорогостоящая операция (bcrypt) выполняется только при найденном пользователе err := db.QueryRow("SELECT password FROM users WHERE username=?", username).Scan(&hash) if err != nil { return // мгновенный возврат — не существует } bcrypt.CompareHashAndPassword(hash, password) // занимает ~60-100ms ``` bcrypt по дизайну вычислительно дорог — это нужно для замедления offline-перебора хешей. Но в timing-side-channel это становится явным сигналом: время ответа на «существующий с неверным паролем» отличается от «несуществующий» на порядки. Атакующий через серию замеров (curl + `--write-out '%{time_total}'`, Python с `time.time()`) с разными username получает чёткий сигнал, какие учётки реально есть в системе. Дальше работают другие техники (brute-force подобранных учёток, password-spray по полученному списку). ## Точка входа атаки | Параметр | Значение | |----------|----------| | Учётные данные | `demo` / `demo` | | Эндпоинт логина | `POST /login` (timing-side-channel в обработке) | | Целевой пользователь | `admin` (имя из публичных конвенций) | | Привилегированный эндпоинт | `GET /admin` (флаг отображается на странице) |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru