
CVE-2026-29000 - pac4j-jwt (< 4.5.9 / < 5.7.9 / < 6.3.3) JwtAuthenticator contournement d'authentification PoC
JwtAuthenticator de pac4j-jwtUne preuve de concept pour CVE-2026-29000, un contournement d'authentification dans le composant JwtAuthenticator de pac4j-jwt (CVSS 10.0, Critique).
Le script forge un jeton qui usurpe l'identité de n'importe quel utilisateur avec n'importe quel rôle — sans connaître un seul secret — tant que la cible expose sa clé publique RSA.
[!WARNING] Cet outil est fourni uniquement à des fins éducatives et de tests de sécurité autorisés. Il a été écrit pour résoudre la machine Hack The Box "Principal", et les valeurs par défaut (
iss,role,kid) sont adaptées à cette machine. Utilisez-le uniquement contre des systèmes que vous possédez ou pour lesquels vous êtes explicitement autorisé à tester.
Les versions < 4.5.9, < 5.7.9 et < 6.3.3 de pac4j-jwt contiennent une faille logique dans JwtAuthenticator lorsqu'il traite des JWT chiffrés (JWE).
Lorsque JwtAuthenticator déchiffre un JWE, il tente d'analyser le jeton interne comme un SignedJWT. Si le jeton interne est un PlainJWT non signé (alg: none), l'objet SignedJWT revient null et, en raison de l'erreur logique, le chemin de vérification de signature est complètement ignoré. L'authentificateur construit alors un profil utilisateur directement à partir des revendications non vérifiées.
En d'autres termes, le chiffrement JWE externe — qui ne nécessite que la clé publique du serveur — est confondu avec une preuve d'authenticité, de sorte que tout attaquant capable de lire la clé publique peut créer des jetons entièrement fiables.
/api/auth/jwks).PlainJWT non signé (alg: none) avec des revendications choisies par l'attaquant (sub, role, iss, …).PlainJWT dans une enveloppe JWE chiffrée avec la clé publique de la cible.Bearer. Le JwtAuthenticator vulnérable le déchiffre, ignore la vérification de signature et fait confiance aux revendications forgées.requirements.txt :pip install -r requirements.txt
(requests, jwcrypto, cryptography)
python3 exploit.py -u <username> [options]
| Flag | Description | Défaut |
|---|---|---|
-t, --target | URL de base de la cible (ex. http://host:8080) | — |
--jwks-url | Chemin de l'endpoint JWKS | /api/auth/jwks |
--jwks-file | Charger JWKS depuis un fichier local au lieu de le récupérer depuis --target | — |
-u, --username | Valeur pour la revendication sub (obligatoire) | — |
--role | Valeur pour la revendication role | ROLE_ADMIN |
--iss | Valeur pour la revendication iss | principal-platform |
--exp | Durée de validité du jeton en secondes | 3600 |
--verify-endpoint | Endpoint protégé pour tester le jeton forgé (ex. /api/settings) | — |
-k, --insecure | Désactiver la vérification du certificat TLS | désactivé |
-o, --output | Écrire le JWE forgé dans un fichier au lieu de stdout | stdout |
-v, --verbose | Afficher la charge utile du JWT forgé sur stderr | désactivé |
Vous devez fournir soit --target (pour récupérer le JWKS via le réseau) soit --jwks-file (pour le fournir localement).
Forger un jeton administrateur en récupérant la clé publique de la cible et l'afficher sur stdout :
python3 exploit.py -t http://target:8080 -u admin
Forger un jeton, puis le tester automatiquement contre un endpoint protégé :
python3 exploit.py -t http://target:8080 -u admin \
--verify-endpoint /api/settings -v
Utiliser un JWKS sauvegardé localement et enregistrer le jeton dans un fichier :
python3 exploit.py --jwks-file jwks.json -u admin -o token.jwe
Mettez à jour org.pac4j:pac4j-jwt vers une version corrigée :
Publié sous la Licence MIT.