Je suis en train de créer une application d'une seule page avec un front-end JavaScript/HTML. Le front-end appelle une API WEB écrite en .NET. Actuellement, j'ai une page HTML où un utilisateur entre ses informations d'identification et clique sur connexion. Une demande AJAX est ensuite envoyée à l'API WEB qui authentifie l'utilisateur et renvoie un cookie HTTP uniquement contenant un jeton Web Json. Le navigateur envoie ensuite ce cookie à chaque demande suivante, et le le contrôleur le valide.
Ce qui précède fonctionne bien, mais il manque de protection CSRF. J'essaie de trouver la meilleure façon de mettre cela en œuvre. D'après mes recherches, il semble qu'il y ait quelques options.
L'article sur https://www.jamesward.com/2013/05/13/securing-single-page-apps-and-rest-services suggère d'extraire un jeton d'un cookie, puis de le soumettre. comme en-tête de demande. Pour ce faire, je devrais supprimer le drapeau HTTP uniquement, afin que JavaScript puisse accéder au cookie. Je ne pense pas que ce soit la meilleure solution, car elle pourrait exposer les informations de session si une vulnérabilité XSS était trouvée. Y a-t-il quelque chose qui me manque?
Quelque part ailleurs, j'ai lu comment envoyer un cookie séparé qui contenait le jeton CSRF et en extraire la valeur avec JavaScript. Ensuite, en envoyant cette valeur sous la forme d'un en-tête personnalisé sur les AJAX requêtes suivantes et en validant l'API WEB sur la base de cet en-tête. J'ai écrit une application de preuve de concept rapide pour cela et découvert que le navigateur enverra toujours le cookie dans lequel le jeton CSRF a été remis lors de futures demandes. Cela pose-t-il un problème? Une page avec une attaque CSRF pourrait-elle l'exploiter?
Similaire à ce qui précède, mais au lieu de livrer le jeton CSRF via un cookie, remettez-le via un en-tête personnalisé et demandez à JavaScript de le lire à partir de là. Cela semble être le plus simple, mais voyez-vous des inconvénients avec cette approche?
En outre, est-il sûr de continuer à utiliser un seul jeton CSRF pour la session entière d'un utilisateur, ou doit-il être actualisé à chaque demande?
Vous pouvez utiliser les stratégies de jetons CSRF classiques, mais leur utilisation dans les applications basées sur AJAX peut prendre un certain effort, et des options plus simples sont disponibles pour les points de terminaison spécifiques à AJAX:
Ajoutez un en-tête supplémentaire aux demandes à votre serveur comme "X-Requested-With: XMLHttpRequest" ou "X-Is-Local-XHR: true", et faites en sorte que votre serveur requiert l'en-tête sur les demandes authentifiées. Les utilisateurs avec d'anciennes versions de Flash peuvent être vulnérables (bien que les anciennes versions de Flash aient également des vulnérabilités bien pires, donc votre choix si cela est important pour vous). Voir https://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header
Vérifiez que l'en-tête Origin ou Referer est défini et correspond au domaine dans l'en-tête Host. L'en-tête Origin est envoyé pour toutes les demandes POST par Chrome et Firefox, mais les anciens navigateurs peuvent ne pas l'inclure. L'en-tête Referer est désactivé par certains utilisateurs pour des raisons de confidentialité) La présence de l'un ou l'autre avec une valeur valide suffit pour vérifier la demande.
C'est un vieux sujet et il y a beaucoup de discussions dispersées (y compris ici sur Security.SE). Cependant, au lieu de la suggestion courante d'émuler un schéma de protection CSRF basé sur les cookies et post-back, je vous propose de supprimer complètement les cookies.
Traitez votre application d'une seule page comme une véritable APP et faites-la authentifier auprès des API Web à l'aide des méthodes standard. Par exemple, vous pouvez utiliser OAuth et demandes sans session. (Si OAuth est trop difficile à configurer, pourrait utiliser un schéma de jetons personnalisé.)
Cela résout également les problèmes avec CORS.