Question:
Pourquoi actualiser le jeton CSRF par demande de formulaire?
Philipp Gayret
2012-10-20 16:15:45 UTC
view on stackexchange narkive permalink

Dans de nombreux tutoriels et guides, je vois qu'un jeton CSRF doit être actualisé à chaque demande. Ma question est: pourquoi dois-je faire cela? Un seul jeton CSRF par session n'est-il pas beaucoup plus facile que d'en générer un par demande et de garder une trace de ceux demandés?

La génération du jeton sur une base par demande ne semble pas améliorer la sécurité au-delà de ce qu'un le jeton par session ferait déjà l'affaire. Le seul argument semble être la protection XSS, mais cela ne s'applique pas car lorsque vous avez une vulnérabilité XSS, le script peut de toute façon lire de nouveaux jetons.

Quels sont les avantages de générer de nouveaux jetons par requête?

Huit réponses:
#1
+113
bobince
2012-10-22 01:31:40 UTC
view on stackexchange narkive permalink

Pour les raisons déjà évoquées, il n'est pas nécessaire de générer un nouveau token par requête. Il n'apporte pratiquement aucun avantage de sécurité et vous coûte en termes de convivialité: avec un seul jeton valide à la fois, l'utilisateur ne pourra pas naviguer normalement dans l'application Web. Par exemple, s'ils cliquent sur le bouton «retour» et soumettent le formulaire avec de nouvelles valeurs, la soumission échouera et les accueillera probablement avec un message d'erreur hostile. S'ils essaient d'ouvrir une ressource dans un deuxième onglet, ils trouveront que la session est interrompue au hasard dans un ou les deux onglets. Cela ne vaut généralement pas la peine de mutiler la convivialité de votre application pour satisfaire cette exigence inutile.

Il y a un endroit où il vaut la peine d'émettre un nouveau jeton CSRF, cependant: sur le changement de principal à l'intérieur une session. C'est, principalement, à la connexion. Ceci afin d'éviter une attaque de fixation de session conduisant à une possibilité d'attaque CSRF.

Par exemple: un attaquant accède au site et génère une nouvelle session. Ils prennent l'ID de session et l'injectent dans le navigateur d'une victime (par exemple via l'écriture d'un cookie à partir d'un domaine voisin vulnérable, ou en utilisant une autre vulnérabilité comme les URL jsessionid), et injectent également le jeton CSRF dans un formulaire dans le navigateur de la victime. Ils attendent que la victime se connecte avec ce formulaire, puis utilisent un autre message de formulaire pour amener la victime à effectuer une action avec le jeton CSRF toujours actif.

Pour éviter cela, invalidez le jeton CSRF et émettez-en un nouveau aux endroits (comme la connexion) où vous faites déjà de même avec l'ID de session pour éviter les attaques de fixation de session.

Ce conseil est-il toujours valable maintenant que les attaques BREACH sont une chose?
Les attaques BREACH sont censées être résolues à une couche différente (en désactivant la compression des données d'application ET la compression TLS), donc la réponse est: vous ne devriez pas vous soucier de l'attaque BREACH sauf si vous configurez TLS ou le serveur HTTP
#2
+23
D.W.
2012-10-21 04:55:57 UTC
view on stackexchange narkive permalink

Présentation. Le conseil standard est d'utiliser un jeton CSRF unique, unique pour chaque demande. Pourquoi? Parce qu'un jeton par demande est un peu plus résistant à certains types d'erreurs d'implémentation qu'un jeton par session. Cela fait des jetons par demande sans doute le meilleur choix pour le développement de nouvelles applications Web. De plus, aucun auditeur de sécurité ne vous dérangera pour l'utilisation d'un jeton CSRF par requête.

Si vous êtes un développeur d'applications Web, c'est tout ce que vous devez savoir, et vous pouvez arrêter de lire ici. Mais si vous êtes un expert en sécurité et que vous vous interrogez sur la justification détaillée de ce conseil, ou si vous vous demandez à quel point le risque est élevé si vous utilisez un jeton par session, lisez la suite ....


Creuser un peu plus loin. La vérité est que, si vous n'avez aucune autre vulnérabilité dans votre site Web, un seul jeton CSRF par session est acceptable. Il n'y a aucune raison pour que vous ayez nécessairement à générer un nouveau jeton CSRF par demande.

Ceci est démontré par le fait que vous trouverez également des experts en sécurité réputés qui disent qu'un autre La manière de se défendre contre CSRF est d'utiliser la double soumission de cookie: en d'autres termes, vous utilisez du Javascript côté client qui calcule un hachage du cookie de session et l'ajoute à chaque requête POST, en traitant le hachage comme le jeton CSRF. Vous pouvez voir que cela génère essentiellement à la volée un jeton CSRF qui est le même pour toute la session.

Bien sûr, je connais l'argument pour lequel certaines personnes pourraient recommander de générer un nouveau jeton CSRF pour chaque requête. Ils pensent que si vous avez également une vulnérabilité XSS sur votre site Web, si vous utilisez un seul jeton CSRF par session, il sera facile d'utiliser XSS pour récupérer le jeton CSRF, alors que si vous générez un nouveau jeton CSRF par requête, il prendra plus de travail pour récupérer le jeton CSRF. Personnellement, je ne trouve pas cet argument très convaincant. Si vous avez une vulnérabilité XSS sur votre site, il est toujours possible de récupérer des jetons CSRF même si vous générez un nouveau jeton CSRF pour chaque requête, cela ne prend que quelques lignes supplémentaires de Javascript malveillant. Quoi qu'il en soit, si vous avez une vulnérabilité XSS sur votre site et que vous faites face à un attaquant sérieux et bien informé, il est difficile de garantir la sécurité, quelle que soit la façon dont vous générez vos jetons CSRF.

Dans l'ensemble, cela ne peut pas nuire pour générer un nouveau jeton CSRF pour chaque demande. Et peut-être vaut-il mieux le faire de cette façon, juste pour vous débarrasser des auditeurs de sécurité. Mais si vous avez déjà une application héritée qui utilise un seul jeton CSRF pour toute la session, dépenser de l'argent pour le convertir afin de générer un nouveau jeton CSRF pour chaque demande ne serait probablement pas très haut sur ma liste de priorités: je parie que je pourrait trouver d'autres utilisations de cet argent et de l'énergie des développeurs qui amélioreraient encore plus la sécurité.

Je ne les appellerais pas des "experts en sécurité réputés" s'ils recommandent la soumission de double cookie ... XSS n'est pas le seul problème à résoudre pour cela. OWASP a un bon aperçu à ce sujet ...
@AviD, double soumettre des cookies est parfaitement bien. Je n'ai encore vu aucune preuve que cette approche est sensiblement plus vulnérable que toute autre approche. Chaque technique a ses vulnérabilités. Celui-ci n'est pas différent.
@Gili, le problème avec les cookies à double soumission est que cela fait généralement référence au cookie de session normal déjà existant - et cela ne devrait pas être accessible à JavaScript (par exemple en utilisant le drapeau `HttpOnly`). L'utilisation de cette technique peut empêcher l'attaque CSRF, mais ouvrirait le cookie de session à d'autres problèmes, tels que le rendre plus vulnérable à d'éventuelles vulnérabilités XSS. Il existe des techniques qui fonctionnent très bien, sans provoquer d'autres vulnérabilités distinctes.
@AviD, comme mentionné dans http://security.stackexchange.com/q/61110/5002 OWASP indique aux développeurs d'utiliser un cookie séparé pour le jeton CSRF précisément pour cette raison. Vous pouvez conserver l'indicateur `HttpOnly` sur le cookie de session.
@Gili oui, c'est exactement le but.
@AviD, désolé, je ne comprends pas votre point. Vous avez dit que les cookies à double soumission vous obligent à supprimer l'indicateur `HttpOnly` du cookie de session, mais je viens d'expliquer que ce n'est pas le cas (vous pouvez utiliser un cookie séparé pour le jeton de cookies à double soumission). Cela n'invalide-t-il pas votre réclamation initiale?
@Gili, a relu les commentaires d'AviD. Ne manquez pas son utilisation du mot «typiquement». La soumission d'un double cookie signifie généralement la réutilisation du cookie de session. Si quelqu'un recommande la soumission d'un double cookie et qu'il n'a pas de clause de non-responsabilité explicite à l'effet contraire, cela signifie qu'il recommande de réutiliser le cookie de session. Je pense qu'AviD a couvert cela avec ses commentaires ci-dessus.
C'est suffisant. PS: Dans le même ordre d'idées, http://security.stackexchange.com/a/43550/5002 remet en question la valeur de «HttpOnly» contre les attaques XSS.
@Gili, oui, je sais. :-) Je viens de publier une réponse sur la question à laquelle vous avez lié, et également liée à la même discussion sur `HttpOnly`. Merci pour le pointeur et la discussion!
@Gili oui, exactement comme D.W. dit, c'était exactement mon intention.
@AviD, Je suis content que nous soyons tous les deux sur la même longueur d'onde. Merci pour la clarification.
"ça ne peut pas faire de mal de générer un nouveau token CSRF pour chaque demande", ça nuit à la convivialité (?)
Le jeton CSRF pour chaque demande peut être actualisé, mais vous devez vous occuper des appels Ajax.D'une certaine manière, c'est un processus fastidieux, mais l'appel Ajax peut être mis à jour.
#3
+15
rook
2012-10-20 23:24:34 UTC
view on stackexchange narkive permalink

XSS peut être utilisé pour lire un jeton CSRF, même s'il s'agit d'un jeton de soumission unique, c'est un jeu d'enfant. Il est probable que cette recommandation d'un jeton d'envoi unique provienne d'une personne qui ne comprend pas CSRF.

La seule raison d'utiliser un «jeton d'envoi unique» est si vous souhaitez empêcher l'utilisateur de cliquer accidentellement sur Envoyer deux fois. Une bonne utilisation de ceci est d'empêcher l'utilisateur de cliquer deux fois sur "payer" et de facturer accidentellement le client deux fois.

Un CAPTCHA ou demandant le mot de passe actuel de l'utilisateur peut être utilisé comme une mesure anti-CSRF qui ne peut pas être contourné par XSS.

Je recommande de lire la Aide-mémoire de prévention CSRF.

Je ne vois pas comment un CAPTCHA ou la saisie du mot de passe serait sécurisé face à XSS. Cela force simplement l'attaquant à sauter à travers quelques cerceaux supplémentaires.
@CodesInChaos l'attaquant devrait connaître le mot de passe, puis c'est un point discutable.
Si l'utilisateur entre le mot de passe à un moment donné après le xss, l'attaquant peut probablement le voler. Donc, ressaisir le mot de passe aide un peu, mais pas beaucoup.
@CodesInChaos Cela fonctionne bien sur le papier, mais cette attaque proposée a beaucoup moins de chances de réussir dans un scénario réel.
@CodesInChaos, vous avez raison de dire qu'un CAPTCHA ne serait pas pertinent pour cela. D'autre part, la réauthentification (sélective sur les actions sensibles) est l'une des meilleures solutions pour CSRF, et devrait être utilisée davantage. Voir également la discussion de Schneier sur «l'authentification des transactions», qui est similaire, mais pas identique.
Les jetons à usage unique ont encore plus d'avantages (au moins pour les opérations critiques): ils ajoutent une sécurité contre les [attaques de relecture] (http://en.wikipedia.org/wiki/Replay_attack).
@Domi Cela dépend de la manière dont ils ont obtenu le jeton en premier lieu. Si c'est avec XSS, ou sur un canal non sécurisé, le jeton roulant n'aurait pas d'importance.
Ils ajoutent toujours une sécurité contre les attaques de relecture, étant donné qu'il n'y a pas de XSS.
#4
+6
Polynomial
2012-10-20 18:37:03 UTC
view on stackexchange narkive permalink

Si le jeton est le même pendant toute la session, il peut être possible pour un attaquant de divulguer un jeton d'une page et de l'utiliser pour une action différente.

Par exemple, vous pouvez utiliser un iframe pour charger une page, puis extraire le jeton à l'aide d'une vulnérabilité XSS. À partir de là, vous pouvez utiliser ce jeton pour soumettre un formulaire de changement de mot de passe

L'utilisation d'un jeton par demande au lieu d'un jeton à l'échelle de la session rend les choses plus difficiles, mais cela n'empêche pas CSRF. Un attaquant peut simplement exploiter un XSS pour lire le jeton de la page, puis le déclencher. Cependant, si le jeton est global plutôt que limité à cette page individuelle, un attaquant peut cibler n'importe quelle page pour voler le jeton. L'utilisation de jetons séparés pour chaque demande rend cela beaucoup plus difficile.

Il n'y a aucun moyen pour quelqu'un d'extraire quoi que ce soit de l'iframe, cela enfreindrait la [même politique d'origine] (http://en.wikipedia.org/wiki/Same_origin_policy)
@SkPhilipp Désolé, je voulais dire via XSS.
L'utilisation d'un XSS devrait être possible pour extraire le jeton même s'il est actualisé à chaque demande. Ai-je raison?
Oui, via XSS, vous pouvez ensuite charger une iframe dans un formulaire de changement de mot de passe, et vous pouvez extraire ce jeton, générer de nouveaux jetons ne le rendrait pas sécurisé si vous avez une vulnérabilité XSS.
-1 Je suis désolé, mais je ne veux pas que les gens aient l'idée que s'ils utilisent un seul jeton de soumission, ils sont protégés par magie contre XSS, car c'est très faux. Si un utilisateur peut le faire dans un navigateur Web, alors xss peut le faire dans un navigateur Web.
@Rook Hein? Je n'ai jamais dit que l'utilisation d'un seul jeton était une bonne chose ...
Si vous avez une vulnérabilité XSS, vous pouvez utiliser un XHR pour lire n'importe quelle page et soumettre n'importe quelle demande. Avoir un jeton différent sur chaque page n'aide pas.
@Rook Je ne dis pas que cela résout le problème entièrement, mais cela rend la tâche plus difficile si vous utilisez des jetons individuels et les verrouillez à des demandes spécifiques. Je peux comprendre pourquoi vous craignez que la réponse ne donne une mauvaise impression.
#5
+3
SilverlightFox
2015-11-30 16:45:14 UTC
view on stackexchange narkive permalink

Suite aux autres réponses, il peut être judicieux d'actualiser également le jeton si votre serveur est sensible à l ' attaque BREACH.

Cela nécessite les trois conditions suivantes:

  • Être servi à partir d'un serveur qui utilise la compression de niveau HTTP
  • Refléter les entrées utilisateur dans les corps de réponse HTTP
  • Refléter un secret (tel en tant que jeton CSRF ) dans les corps de réponse HTTP

Pour atténuer BREACH, vous devez actualiser le jeton CSRF sur la requête GET qui charge un formulaire pour invalider tous les jetons précédents. De cette façon, un MITM (Man-In-The-Middle) créant des requêtes supplémentaires pour découvrir le jeton dans la page recevra un jeton différent à chaque fois. Cela signifie que l'utilisateur réel ne pourra pas soumettre le formulaire dans une situation MITM.

Bien sûr, vous avez besoin que les deux autres conditions soient également vraies. Il serait probablement plus facile de gérer un jeton CSRF par session et de désactiver la compression de niveau HTTP pour toutes les pages qui servent des formulaires.

#6
+2
user2428118
2015-07-17 15:45:15 UTC
view on stackexchange narkive permalink

Ce n'est pas un fait très connu, mais la comparaison de chaînes normale est vulnérable aux attaques de synchronisation ( comme celle-ci. En bref, opérations de comparaison de chaînes normales ( == ou === ) comparera deux chaînes caractère par caractère de gauche à droite et retournera false une fois qu'elles auront rencontré un caractère différent à une position donnée dans les deux chaînes. Cela donne un minuscule différence de timing qui a été prouvée détectable.

En utilisant une attaque de synchronisation pour essayer tous les caractères possibles pour chaque position, il est possible de déterminer quel est le jeton réel. En créant un nouveau jeton à chaque fois qu'une demande avec un jeton est soumise, cette attaque peut être évitée.

Bien sûr, cela ne fonctionne que si vous recréez également le jeton si un invalide Le jeton a été soumis, ce qui n'est peut-être pas souhaitable. Par conséquent, vous feriez mieux de résoudre ce problème en utilisant une fonction de comparaison de chaînes insensible au temps telle que celle-ci.

D'accord, mais je dois noter dans les exemples et dans l'article que vous avez répertorié un attaquant théorique qui pourrait mesurer très précisément le temps d'horloge du processeur. La machine n'était soumise à aucune autre charge et de nombreuses langues utilisent des codes de hachage précalculés pour la comparaison de chaînes avant d'effectuer une vérification caractère par caractère.
Les comparaisons à temps constant peuvent et doivent être utilisées pour atténuer cela (boucle sur tous les caractères et x ou un indicateur de différence).
#7
  0
edruid
2015-04-23 20:30:37 UTC
view on stackexchange narkive permalink

L'une des raisons pour lesquelles vous souhaitez modifier le jeton CSRF par requête est d'atténuer la fuite de compression du jeton. Ce que je veux dire par là, c'est que si l'attaquant Eve peut injecter des données sur une page contenant le jeton où la page est envoyée compressée, Eve peut alors deviner le premier caractère de la chaîne recevant un ensemble de données plus petit pour la page en sachant qu'elle a bien deviné alors allez au caractère suivant.

Ceci est similaire à une attaque de synchronisation.

Pour le moment, il n'y a aucune raison (à ma connaissance) de changer le jeton s'il n'est envoyé que dans les en-têtes HTTP.

Une autre méthode consiste à changer le jeton dès qu'une requête ayant échoué est découverte, mais cela pourrait poser des problèmes avec l'utilisateur qui ne peut soumettre aucun formulaire.

#8
-1
Bhuvanesh
2015-07-17 12:37:51 UTC
view on stackexchange narkive permalink

Si le même jeton est utilisé pour toute la session, il est alors probable que l'attaquant puisse détourner le jeton en utilisant XSS et utiliser la session de la victime pour effectuer des activités malveillantes comme changer le mot de passe .

Ils peuvent modifier les mots de passe en ajoutant une iframe au site que vous utilisez.

Il est donc préférable d'utiliser un jeton par requête pour éviter que l'attaquant ne gagne accès à ce jeton.

Un attaquant utilisant XSS peut accéder à de nouveaux tokens, c'est de cela que porte toute la question. Voir aussi les commentaires sur http://security.stackexchange.com/a/22904/15195


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...