Diviser un JWT entre la charge utile et la signature
Contexte: je suis à la recherche de solutions de stockage pour les jetons JWT sur une seule application de page.
- Le stockage du JWT dans le stockage local est dangereux et sujet aux attaques XSS.
- Le stockage du JWT dans un cookie sécurisé / HTTP uniquement est plus sûr, mais sujet aux attaques CSRF.
J'étudie le scénario suivant:
Lors de l'authentification, un jeton d'actualisation est stocké dans un cookie http uniquement sécurisé. Il ne peut être utilisé que pour obtenir un jeton d'accès.
Lors de l'autorisation, le backend répond avec un jeton d'accès JWT. L'en-tête et la partie charge utile du JWT se trouvent dans le corps de la réponse. La signature du jeton n'est pas envoyée et est définie dans un cookie sécurisé uniquement http (même site strict si possible, mais supposons que ce n'est pas le cas). L'en-tête + la charge utile sont stockés en mémoire.
Le JWT contient les revendications suivantes
- iat, nbf, exp (IMO devinable)
- revendications relatives à l'identité et aux autorisations de l'utilisateur (devinable si l'identité de l'utilisateur est connue)
- jti, contenant un nombre aléatoire sécurisé cryptographiquement (dans mon cas, généré avec des secrets python )
Lors des demandes, l'en-tête + la charge utile sont envoyés via XHR / fetch par le SPA dans un en-tête d'autorisation. La signature est envoyée avec les cookies. Le backend concatène les deux et vérifie la signature.
- Ce mécanisme est-il sûr contre les attaques CSRF? Les revendications JTI font-elles du jeton d'autorisation + cookie de signature une technique d'atténuation CSRF valide?
- Ce mécanisme est-il en effet plus sûr contre les attaques XSS que de stocker le JWT dans le stockage local? (Une attaque utilisant XSS pourrait-elle également voler facilement la signature, comme avec un exploit TRACE ).
Remarque: j'ai lu cette question qui est similaire, mais trop large, donc je la poste pour obtenir une réponse plus précise.
Réponses
Ce mécanisme est-il sûr contre les attaques CSRF?
Cette méthode de division d'un JWT et de stockage de la signature dans le cookie et le reste du jeton dans le stockage du navigateur ne fournit aucune protection supplémentaire contre les attaques CSRF que si le JWT entier était stocké dans le stockage local ou de session. Oui, cela atténuera les attaques CSRF, mais vous n'avez pas besoin d'ajouter la surcharge inutile de fractionnement et de concaténation des JWT sur le serveur. Stocker les JWT dans le stockage local et les accepter uniquement dans les en-têtes d'autorisation suffit à protéger votre application contre les attaques CSRF.
Ce mécanisme est-il en effet plus sûr contre les attaques XSS que de stocker le JWT dans le stockage local? (Une attaque utilisant XSS pourrait-elle également voler facilement la signature, comme avec un exploit TRACE)
Si vous vous concentrez uniquement sur un attaquant capable de voler des JWT, cette approche est sûre sauf si, comme vous l'avez mentionné à juste titre, TRACE est activé sur le serveur.
Cependant, cela ne rend pas votre application plus sûre contre les attaques XSS. Par exemple, si je suis capable d'exécuter du Javascript arbitraire sur votre application, je peux récupérer l'en-tête JWT + la charge utile à partir du stockage local et simplement envoyer un XHR à un point de terminaison sensible en gardant les identifiants définis sur True. Ce point de terminaison peut être conçu pour modifier l'adresse e-mail du compte, par exemple. Cela conduit aussitôt à une reprise de compte. Pas besoin de voler des cookies ou des JWT.
En résumé: cette approche offre une certaine protection contre les jetons de session en séparant la signature du reste du jeton. Cependant, en ce qui concerne XSS, le vol de jetons de session n'est pas le seul risque à prendre en compte.