J'ai besoin d'un jeton CSRF, pour une certaine application qui soumet un formulaire avec POST
. Idéalement, j'aimerais ne pas faire d'appel DB pour chaque soumission, afin d'éviter le stockage, le trafic DB et la latence. À cette fin "la feuille de triche de prévention CSRF de l'OWASP" dit,
Présentation
Le modèle de jeton crypté exploite une méthode de cryptage, plutôt qu'une comparaison, de validation de jeton. Une fois l'authentification réussie, le serveur génère un jeton unique composé de l'ID de l'utilisateur, d'une valeur d'horodatage et d'un nonce, à l'aide d'une clé unique disponible uniquement sur le serveur. Ce jeton est retourné au client et intégré dans un champ caché. […] Les requêtes non AJAX basées sur un formulaire conserveront implicitement le Token dans son champ caché. À la réception de cette demande, le serveur lit et déchiffre la valeur du jeton avec la même clé utilisée pour créer le jeton. […]
Validation
En cas de décryptage de jetons réussi, le serveur a accès à des valeurs analysées, idéalement sous la forme de revendications.
La première ligne de "Validation" se lit, pour moi, comme la définition même d'un JWT . Je ne vois pas non plus pourquoi les informations contenues dans le jeton doivent être chiffrées: il semblerait qu'il suffit simplement d'authentifier qu'elles proviennent du serveur (par opposition à un attaquant qui tente de forger un jeton CSRF.)
Y a-t-il une raison particulière de crypter les jetons CSRF? Sinon, un JWT suffit-il?
En outre, le modèle de jeton ci-dessus comprend un nonce. Quel est l'intérêt du nonce? (L'intérêt de ce modèle est de ne stocker aucun état côté serveur. Si je ne stocke pas d'état, comment puis-je utiliser le nonce pendant la validation de quelque manière matérielle?)
Ma principale raison de poursuivre les JWT ici est qu'il y a un support de bibliothèque décent, je vais probablement les vouloir pour l'authentification tôt ou tard, et cela m'empêche surtout d'implémenter des trucs cryptographiques.
Ma compréhension des JWT est que si j'avais des JWT pour l'authentification complète des utilisateurs, je pourrais les stocker dans localStorage
, et simplement les ajouter à un champ avec JS avant la soumission du formulaire. Malheureusement, l'application utilise l'authentification basée sur les cookies, et je ne suis pas en mesure de modifier cet aspect pour le moment.
Il n'est pas nécessaire de chiffrer le jeton ou d'inclure le nonce. Les principales propriétés d'un jeton CSRF sont qu'il n'est pas prévisible par un attaquant et, contrairement aux cookies, qu'il n'est pas ajouté à chaque demande du navigateur. Un cryptographiquement sécurisé JWT stocké dans un champ caché répond à ces deux propriétés.
Notez que vous devez utiliser des JWT contenant des données uniques à l'utilisateur. Avoir un JWT vide ou générique qui n'est pas spécifique à l'utilisateur ne vous fournira pas de sécurité.
TL; DR
Un JWT, s'il est utilisé sans cookies, annule le besoin d'un jeton CSRF - MAIS! en stockant JWT dans session/localStorage, vous exposez votre JWT et l'identité de l'utilisateur si votre site a une vulnérabilité XSS (assez courante). Il est préférable d'ajouter une clé csrfToken
au JWT et de stocker le JWT dans un cookie avec secure
et http-only
ensemble d'attributs.
Lisez cet article avec une bonne description pour plus d'informations https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage
Vous pouvez rendre cette protection CSRF sans état en incluant une revendication xsrfToken JWT:
{ "iss": "http://galaxies.com", "exp": 1300819380, "scopes": ["Explorer", "solar-harvester", "seller"], "sub": "[email protected]", "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e" }
Vous devrez donc stocker le csrfToken dans local/sessionStorage ainsi que à l'intérieur du JWT (qui est stocké dans un cookie sécurisé http uniquement). Ensuite, pour la protection csrf, vérifiez que le jeton csrf dans le JWT correspond à l'en-tête csrf-token soumis.
Vous pouvez utiliser un JWT comme jeton CSRF, mais ce serait inutilement compliqué: un jeton CSRF n'a pas besoin de contenir de revendications, ni d'être chiffré ou signé.
Il y a probablement un malentendu quant à l'utilisation des jetons JWT ou CSRF (j'étais confus au début aussi). Le JWT est un jeton d'accès, utilisé pour l'authentification. Le jeton CSRF, d'autre part, est utilisé pour empêcher l'utilisateur d'être trompé en envoyant une demande authentifiée falsifiée. Cela est nécessaire lors de l'utilisation d'une session ou d'une authentification de base HTTP ou du stockage du JWT dans un cookie - toute authentification effectuée automatiquement par le navigateur.
Si vous disposez d'un tel schéma d'authentification, assurez-vous
Lisez, par exemple, comment Spring gère CSRF .