J'essaie de comprendre tout le problème du CSRF et les moyens appropriés de le prévenir. (Ressources que j'ai lues, comprises et approuvées: Aide-mémoire sur la prévention de la CSRF de l'OWASP , Questions sur la CSRF .)
Si je comprends bien, la vulnérabilité autour de CSRF est introduite par l'hypothèse que (du point de vue du serveur Web) un cookie de session valide dans une requête HTTP entrante reflète les souhaits d'un utilisateur authentifié. Mais tous les cookies du domaine d'origine sont magiquement attachés à la demande par le navigateur, donc tout ce que le serveur peut inférer de la présence d'un cookie de session valide dans une demande est que la demande provient d'un navigateur qui a une session authentifiée; il ne peut plus rien supposer du codeen cours d'exécution dans ce navigateur, ou s'il reflète vraiment les souhaits des utilisateurs. Le moyen d'empêcher cela est d'inclure des informations d'authentification supplémentaires (le "jeton CSRF") dans la demande, véhiculées par un autre moyen que la gestion automatique des cookies du navigateur. En gros, le cookie de session authentifie l'utilisateur / navigateur et le jeton CSRF authentifie le code exécuté dans le navigateur.
Donc, en résumé, si vous utilisez un cookie de session pour authentifier les utilisateurs de votre application Web, vous devez également ajouter un jeton CSRF à chaque réponse et exiger un jeton CSRF correspondant dans chaque demande (de mutation). Le jeton CSRF effectue ensuite un aller-retour du serveur au navigateur pour revenir au serveur, prouvant au serveur que la page faisant la demande est approuvée par (générée par, même) ce serveur.
Passons à ma question, qui concerne la méthode de transport spécifique utilisée pour ce jeton CSRF lors de cet aller-retour.
Il semble courant (par exemple dans AngularJS , Django , Rails ) d'envoyer le jeton CSRF du serveur au client sous forme de cookie (c'est-à-dire dans un en-tête Set-Cookie), puis de laisser Javascript dans le client le gratter du cookie et le joindre en tant qu'en-tête XSRF-TOKEN distinct à renvoyer au serveur.
(Une autre méthode est celle recommandée par exemple par Express , où le jeton CSRF généré par le serveur est inclus dans le corps de la réponse via l'expansion du modèle côté serveur, attaché directement au code / balisage qui le fournira au serveur, par exemple en tant qu'entrée de formulaire masquée. Cet exemple est une façon de faire plus Web 1.0, mais généraliserait bien à un client plus lourd en JS.)
Pourquoi est-il si courant d'utiliser Set-Cookie comme transport en aval pour le jeton CSRF / pourquoi est-ce une bonne idée? J'imagine que les auteurs de tous ces cadres ont soigneusement examiné leurs options et ne se sont pas trompés. Mais à première vue, l'utilisation de cookies pour contourner ce qui est essentiellement une limitation de conception des cookies semble idiote. En fait, si vous utilisiez des cookies comme transport aller-retour (Set-Cookie: en-tête en aval pour que le serveur indique au navigateur le token CSRF, et Cookie: en-tête en amont pour que le navigateur le retourne au serveur), vous réintroduiriez la vulnérabilité que vous essaient de réparer.
Je me rends compte que les cadres ci-dessus n'utilisent pas de cookies pour l'ensemble du trajet aller-retour pour le jeton CSRF; ils utilisent Set-Cookie en aval, puis quelque chose d'autre (par exemple un en-tête X-CSRF-Token) en amont, et cela ferme la vulnérabilité. Mais même utiliser Set-Cookie comme transport en aval est potentiellement trompeur et dangereux; le navigateur attachera maintenant le jeton CSRF à chaque demande, y compris les demandes XSRF malveillantes authentiques; au mieux, cela rend la demande plus importante qu'elle ne devrait l'être et au pire, un morceau de code de serveur bien intentionné mais mal orienté pourrait en fait essayer de l'utiliser, ce qui serait vraiment mauvais. De plus, étant donné que le destinataire prévu du jeton CSRF est le Javascript côté client, cela signifie que ce cookie ne peut pas être protégé avec http uniquement.