Injection d'en-tête JWK JWT
| Gravité | Élevée |
|---|---|
| CVE | |
| Classifications | CWE-345: Insufficient Verification of Data Authenticity |
| Schéma d’attaque | CAPEC-194: Fake the Source of Data |
| Catégorie OWASP | OWASP API2:2023 Broken Authentication |
Le champ d’en-tête JWT jwk (RFC 7515 §4.1.3) permet à un token d’embarquer la clé publique nécessaire pour vérifier sa propre signature. Il existe pour les cas où le vérificateur ne possède pas encore le matériel de clé du signataire. Certaines bibliothèques JWT — notamment les premières versions de express-jwt/jsonwebtoken (CVE-2018-0114) — faisaient implicitement confiance à n’importe quelle clé embarquée là, au lieu de la vérifier contre un jeu de clés connu, épinglé, ou l’endpoint JWKS propre du serveur.
Un attaquant qui contrôle cette faille de confiance génère simplement sa propre paire de clés, embarque la partie publique dans l’en-tête jwk, et signe le token avec la clé privée correspondante. Comme le serveur extrait et utilise la clé fournie par l’attaquant pour vérifier la signature fournie par l’attaquant, la vérification réussit toujours — pour n’importe quels claims choisis par l’attaquant.
Exemple
Section titled “Exemple”Voici un JWT valide signé en RS256 avec la vraie clé du serveur :
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.<signature>L’attaquant génère une nouvelle paire de clés RSA, embarque la clé publique dans l’en-tête jwk, définit kid en correspondance, et re-signe avec la partie privée :
{ "alg": "RS256", "typ": "JWT", "kid": "jwk-injection", "jwk": { "kty": "RSA", "use": "sig", "kid": "jwk-injection", "alg": "RS256", "n": "xXMZbZPrGVs550WbJ0FJRMLijFY7wDDME1dV88KGQPzJ...", "e": "AQAB" }}Un serveur vulnérable lit la clé publique directement depuis jwk, vérifie la signature avec (ce qui réussit — l’attaquant a signé avec la clé privée correspondante), et traite le token comme authentique.
Comment tester ?
Section titled “Comment tester ?”Si vous voulez tester si votre serveur est vulnérable à la vulnérabilité « JWT JWK Header Injection », vous pouvez utiliser la commande crack :
jwtop crack [token] --url [url]La vérification ne s’exécute que contre les tokens RSA/ECDSA (RS*/ES*/PS*) — un serveur qui fait confiance à un jwk embarqué n’a aucune raison de le faire pour des tokens signés en HMAC.
Pour générer un token avec un jwk auto-signé injecté, utilisez la commande exploit jwkinjection :
jwtop exploit jwkinjection [token]jwtop exploit jwkinjection [token] --alg ES256jwtop exploit jwkinjection [token] --key /path/to/private.pemQuel est l’impact ?
Section titled “Quel est l’impact ?”Une attaque par injection JWK réussie permet à un attaquant de forger un JWT que le serveur accepte comme légitime, sans aucune connaissance de la clé de signature réelle du serveur. Cela peut mener à un contournement total de l’authentification, une élévation de privilèges, ou une usurpation d’identité de n’importe quel utilisateur du système.
Comment corriger ?
Section titled “Comment corriger ?”- Ne résolvez jamais la clé de vérification à partir du token lui-même. Ignorez les champs d’en-tête
jwk(etjku,x5u) lors de la vérification — recherchez la clé côté serveur parkiddans un jeu de clés épinglé ou votre propre endpoint JWKS. - Si le support de
jwk/jkuest incontournable, restreignez-le à une liste explicite de clés ou d’émetteurs de confiance, et n’acceptez jamais une clé que le token fournit lui-même comme preuve de sa propre authenticité. - Épinglez l’algorithme et la ou les clés attendues par émetteur afin qu’un token ne puisse pas dicter quelle clé ou famille d’algorithme le vérifie.