web-dev-qa-db-fra.com

Protection CSRF et applications à page unique

Je suis en train d'écrire une application Web cliente épaisse à l'aide d'Angular.js (application à page unique) et je me demandais quelles étaient les meilleures pratiques pour sécuriser l'application à l'aide d'un jeton CSRF.

Dois-je envoyer un jeton CSRF lors du premier chargement de l'application, puis le réutiliser à chaque demande? Dois-je avoir un mécanisme pour actualiser le jeton? Existe-t-il d'autres protections plutôt qu'un jeton CSRF qui auraient plus de sens pour une application d'une seule page?

31
Olivier Lalonde

Eh bien voici comment j'ai fini par implémenter CSRF:

À la première demande, définit un jeton CSRF en tant que cookie. Toutes les demandes AJAX suivantes incluent le jeton CSRF en tant que X-CSRF-Token En-tête HTTP.

Django a une belle documentation sur la façon de le faire proprement avec jQuery: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

Modifier: une approche alternative répertorie les demandes qui contiennent le X-Requested-With entête. Il semble que ce soit ce que Rails fait . Mais comme @damio l'a souligné ci-dessous, le X-Requested-With est un risque pour la sécurité, Django et Rails revvert) de ne plus l'utiliser et de forcer un jeton.

18
Olivier Lalonde

Tu es chanceux! Il y a environ 2 semaines, on m'a posé la même question, et après un peu de grattage de tête, j'ai trouvé ce qui suit. N'oubliez pas que ce n'est pas bien évalué par les pairs, nous verrons donc comment les commentaires et le vote se déroulent. Personnellement, je pense que c'est une bonne technique.

1. Première demande

Une fois que vous avez reçu la première demande de chargement de votre application, générez un identifiant aléatoire sécurisé et stockez-le dans une variable de session sur le serveur, puis envoyez-le au client. Je l'intégrerais dans la page juste avant </body>.

<script>setToken('<% print SESSION[TOKEN] %>');</script>
</body>

Votre setToken() assignerait la valeur du jeton à la variable dans laquelle vous garderiez le jeton.

2. Demandes ultérieures

Avec chaque demande, vous ajoutiez ce jeton à la liste des paramètres, comme token=TOKEN, Et le serveur le comparait à celui stocké dans la variable de session.

. Actualisation du jeton

Ce n'est pas vraiment obligatoire, mais c'est une bonne idée de rafraîchir le jeton de temps en temps, disons 15 minutes. Lorsque vous recevez une demande après l'expiration du jeton (vous avez l'heure d'expiration dans la variable de session), vous y répondez normalement (agissez avec optimisme) mais dans la réponse, vous dites au client que l'ancien jeton a expiré et qu'il devrait commencer à utiliser le nouveau.

Le client réagit à cela en disant au serveur qu'il connaît maintenant le nouveau jeton, une fois que le serveur reçoit cette demande, il commence à utiliser le nouveau jeton et répond au client avec un message OK, une fois que le client reçoit 200 OK, Cela signifie qu'ils sont tous deux synchronisés et que le client commence à utiliser le nouveau jeton.

Remarque: Un élément clé du processus est l'utilisation HTTPS. Vous ne voulez pas qu'un homme au milieu renifle le jeton. Mais là encore, un MitM pourrait renifler les cookies et détourner la session de toute façon.

16
Adi