
Доказательство концепции (PoC) для уязвимости обхода аутентификации, затрагивающей приложения, использующие pac4j-jwt с JWE (JSON Web Encryption).
Дисклеймер: Этот эксплойт был разработан исключительно для вышедшей из ротации машины HackTheBox "Principal". Только в образовательных целях. Не используйте против систем, которыми вы не владеете или на тестирование которых у вас нет явного разрешения.
| Поле | Детали |
|---|
| Название | Principal |
| Платформа | HackTheBox |
| Сложность | — |
| Статус | Вышла из ротации |
Затронутая библиотека: pac4j-jwt < 4.5.9 / 5.7.9 / 6.3.3
Критичность: Критическая
Тип: Обход аутентификации
Логическая ошибка в JwtAuthenticator позволяет атакующему обойти аутентификацию,
обернув неподписанный PlainJWT (alg=none) внутри JWE (зашифрованного JWT).
Когда сервер расшифровывает JWE, он пытается разобрать внутренний токен как
SignedJWT. Поскольку внутренний токен является PlainJWT, объект SignedJWT
равен null, и проверка подписи полностью пропускается. Затем сервер строит
профиль пользователя из непроверенных утверждений — что позволяет полностью
выдать себя за любого пользователя, включая администраторов.
Создание вредоносных утверждений (sub=admin, role=ROLE_ADMIN)
↓
Создание неподписанного PlainJWT (alg=none)
↓
Обёртка PlainJWT внутри JWE с использованием открытого RSA-ключа сервера
↓
Отправка JWE-токена на сервер
↓
Сервер расшифровывает JWE → находит PlainJWT → пропускает проверку подписи → предоставляет доступ
См. exploit.py
Обновите pac4j-jwt до исправленной версии:
4.5.9 или новее5.7.9 или новее6.3.3 или новееИли явно отклоняйте внутренние токены PlainJWT после расшифровки JWE:
if (jwt instanceof PlainJWT) {
throw new CredentialsException("PlainJWT not allowed inside JWE");
}
/api/auth/jwks
alg: noneОберните внутри JWE с помощью открытого ключа
Отправьте как:
Authorization: Bearer <token>
pip install jwcrypto requests
python3 poc.py \
--jwks-url http://target/api/auth/jwks \
--target http://target/api/dashboard
[+] Создан токен:
eyJhbGciOiJSU0EtT0FFUC0yNTYi...
[+] Инъекция в браузер:
sessionStorage.setItem("auth_token", "eyJhbGciOiJSU0EtT0FFUC0yNTYi...")
[+] Статус: 200
{"user":{"username":"admin","role":"ROLE_ADMIN"}}
Откройте DevTools → Консоль:
sessionStorage.setItem("auth_token", "<PASTE_TOKEN_HERE>")
Затем перейдите на:
/dashboard
alg: none