Tour d'horizon de failles connues de JWT

Tout d’abord je dois dire que le titre est clairement trompeur. Il n’y a pas de faille à proprement parler dans la technologie elle-même mais plutôt dans ses implémentations (quelque soit le langage utilisé).

Faisons donc un tour des vulnérabilités plus ou moins connues des implémentations de JWT.

Une bonne situation

Algo “none”

Une vulnérabilité assez vite exploitée fut l’utilisation de la valeur none dans l’entête du JWT. En effet, il est prévu dans la RFC7519 la possibilité d’avoir des jetons non sécurisés en le spécifiant de cette manière :

{
	"alg": "none"
}

Or, si un attaquant récupère un JWT, change cette valeur en mettant none à la place de l’algorithme utilisé et que le serveur qui va vérifier le jeton autorise l’utilisation de none le token sera bien validé. L’attaquant peut donc changer le “payload” du jeton à son gré.

La solution simple et efficace pour se prémunir de ce genre d’attaque est de ne pas tout autoriser, mais uniquement une valeur choisie (voir utiliser une liste d’autorisation).

Une implémentation de cette attaque en PHP est dispo ici.

RSA <=> Hmac

Sur le même genre de modèle que la précédente, cette attaque est un petit peu plus avancée. Il s’agit cette fois de modifier l’algorithme de signature dans le cas où le jeton est signé via une clé asymétrique.

L’attaquant va changer la signature en mettant dans le header un algorithme à clé symétrique, puis en signant le jeton avec la clé publique (puisqu’on le rappelle une clé publique est probablement relativement accessible).

{
	"alg": "RS256"
}

remplacé par ça (exemple) :

{
	"alg": "HS256"
}

puis “re signé”

hash_hmac('sha256', $header . "." . $payload, $publicKey);

Le serveur qui va recevoir le jeton de l’attaquant, s’attend à vérifier le JWT avec sa clé publique. Or, s’il fait l’erreur de se fier à l’algorithme présent dans le header du JWT, il va utiliser un algo à clé symétrique et donc valider le jeton.

Voir une implémentation de cette attaque en PHP ici.

Craquer la clé par brute force

Il n’y a aucun mécanisme de protection contre les attaques par brute force dans JWT.

Un attaquant qui récupère un JWT signé par une clé symétrique, peut donc tenter de retrouver la clé si celle-ci n’est pas suffisament robuste. Dans ce cas, l’attaquant pourra créer et signer ses propres jetons sans problème.

Pour se protéger de ce genre de problème, allez jeter un oeil ici.

Substitution

Imaginons que vous soyez client d’une app qui expose 2 services distincts (tous deux accessibles via JWT) : un sur lequel vous êtes admin, l’autre simple utilisateur.

Il est permis de penser que vous ayez 2 jetons différents : un qui vous permet d’accéder au premier service dont vous êtes admin, et l’autre qui vous permet d’accéder au second service dont vous êtes simple utilisateur.

Que se passerait-il si vous utilisiez le jeton qui vous sert à accéder au premier service, pour appeler le second service ?

Si les 2 services utilisent la même clé de signature, il n’est pas impossible d’imaginer que vous parveniez à avoir des droits augmentés sur le second service.

Alors oui ça fait beaucoup de “si” mais ce qui n’est pas impossible doit être pris en compte. Pour se protéger contre ce genre d’attaque, il faut absolument vérifier que le jeton a bien été émis pour ce service (claim aud). Plus d’info ici.

Altération du contenu chiffré

On peut penser (à tord) que le chiffrement assure systématiquement l’intégrité des données. En fait, ça dépend de l’algorithme utilisé. Certains algorithmes de chiffrement ne le garantissent pas.

Si un attaquant parvient à récupérer un jeton chiffré par un de ces algorithmes, il pourra modifier le contenu du jeton sans avoir besoin de casser le chiffrement.

C’est pourquoi il est primordial de ne pas s’éloigner de la RFC7518 et de n’utiliser que les algorithmes indiqués.

Conclusion

Cette liste n’est pas exhaustive. Il existe d’autres vulnérabilités connues (notamment sur les algo à courbe elliptique).

Globalement s’en protéger n’est pas très compliqué, mais encore faut-il les connaitre et mettre en place ce qu’il faut. Vous pouvez trouver quelques bonnes pratiques relativement simples à appliquer ici.

Si ça vous intéresse, il y a une implémentation PHP de quelques vulnérabilités exploitées ici (attention les yeux, le brute force en PHP est priceless 🔥).