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

JWT: None Algorithm Attack

Сервер принимает JWT с алгоритмом none — подделайте токен без подписи и получите права администратора.

mediumphpPro
Задача
# JWT: обход аутентификации через приём небезопасного алгоритма подписи ## Сценарий Вы — аудитор безопасности **SecureShop** (PHP + Apache + native JWT). Аутентификация построена не на серверных сессиях, а на JWT-токенах: после успешного входа сервер выдаёт клиенту подписанный токен, сохраняет его в cookie `token`, и каждый последующий запрос авторизуется именно по этому токену. Команда разработки уверена, что верификация настроена корректно — токены подписываются HMAC-секретом, который хранится только на сервере, а перед использованием полезной нагрузки сервер пересчитывает HMAC и сверяет с подписью. По данным внутреннего аудита, в админ-панели хранится конфиденциальная метка (CTF-флаг), доступная только пользователям с ролью `admin`. Пароль администратора атакующему неизвестен; ваша задача — получить admin-доступ и извлечь флаг, имея только обычную учётную запись `demo` / `demo`. ## Цель 1. Залогиньтесь как `demo` / `demo` и изучите структуру токена в cookie `token` (заголовок, payload, подпись — три base64url-сегмента, разделённые точками). 2. Найдите способ создать токен с произвольными claims (включая `role: admin`) без знания серверного секрета — иначе говоря, обойти криптографическую проверку подписи. 3. Подмените cookie `token` на собранное значение, откройте `/admin` и извлеките CTF-флаг. ## Теория JWT-токен (RFC 7519) состоит из трёх base64url-частей, разделённых точками: **header**, **payload**, **signature**. Header содержит поле `alg` — имя алгоритма подписи. Payload содержит claims — данные о пользователе. Signature доказывает, что header и payload не изменялись после выдачи токена. Стандарт исторически включал значение `alg: "none"` — «токен без подписи». Этот режим был введён для использования в уже защищённых каналах (mTLS, локальный IPC), но в публичных HTTP-API стал источником массовых уязвимостей. Если сервер при верификации читает поле `alg` из заголовка и попадает в ветку, где для `none` подпись пропускается, проверка фактически отсутствует — атакующий может предъявить любой токен с любыми claims, не зная секрета. В этой лабе верификатор реализован вручную на нативном PHP (`base64`, `hash_hmac`, `hash_equals`). Ошибка в нём — отдельная ветка кода, обрабатывающая `alg = "none"`: она просто возвращает payload без какой-либо проверки. Дополнительно функция получения текущего пользователя перезаписывает поле `role`, прочитанное из БД, значением из claims токена — поэтому подменив `role` в payload, атакующий сразу же получает административные права. **Уязвимый PHP-паттерн:** ```php $alg = strtolower($header['alg'] ?? ''); // VULNERABILITY: accepts "none" — no signature verification if ($alg === 'none') { return $payload; } // ... далее ветка с честной HMAC-проверкой для HS256 // VULNERABILITY: role overridden from JWT claims $user['role'] = $payload['role'] ?? $user['role']; ``` ## Таблица атак на JWT | Класс атаки | Идея | Применима в этой лабе | |-------------|------|----------------------| | `alg: none` | Объявить в заголовке отсутствие подписи; сервер пропускает проверку | **Да** — основной вектор | | HS256 ↔ RS256 (key confusion) | Подменить алгоритм с асимметричного на симметричный, использовать публичный ключ как HMAC-секрет | Нет — сервер использует HS256, асимметричной схемы нет | | Brute-force HMAC-секрета | Подобрать слабый секрет офлайн (hashcat, jwt_tool) | Нет в рамках этой лабы (отдельная категория) | | `kid` path traversal | Подсунуть в заголовке путь к контролируемому атакующим файлу как ключ | Нет — поле `kid` верификатор не использует | | JWK header injection | Передать собственный публичный ключ прямо в заголовке токена | Нет — верификатор использует серверный секрет, не доверяет заголовку | ## Точка входа атаки | Параметр | Значение | |----------|----------| | Обычная учётная запись | `demo` / `demo` | | Эндпоинт логина | `POST /login` (выдаёт cookie `token` с HS256-JWT) | | Имя cookie | `token` | | Кодировка частей токена | base64url без `=`-выравнивания | | Привилегированный эндпоинт | `GET /admin` (требует `role: admin` в подменённом токене) | | Где находится флаг | в HTML-ответе `/admin` в карточке Admin Flag, формат `flag{...}` |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru