web-dev-qa-db-fra.com

Comment se protéger contre la connexion CSRF?

http://seclab.stanford.edu/websec/csrf/csrf.pdf souligne que la plupart des mécanismes de protection CSRF ne parviennent pas à protéger les formulaires de connexion. Comme https://stackoverflow.com/a/15350123/14731 explique:

La vulnérabilité se présente comme suit:

  1. L'attaquant crée un compte Host sur le domaine de confiance
  2. L'attaquant falsifie une demande de connexion dans le navigateur de la victime avec les informations d'identification de ce compte hôte
  3. L'attaquant incite la victime à utiliser le site de confiance, où elle peut ne pas remarquer qu'elle est connectée via le compte Host
  4. L'attaquant a désormais accès à toutes les données ou métadonnées que la victime a "créées" (intentionnellement ou non) alors que son navigateur était connecté avec le compte Host

Cette attaque a été tilisée avec succès contre Youtube .

Les auteurs de l'article ont ensuite proposé l'ajout d'un en-tête "Origine" mais se sont heurtés à la résistance des membres du W3C: http://lists.w3.org/Archives/Public/public-web-security/2009Dec /0035.html

À ce jour, seuls Chrome et Safari implémentent l'en-tête "Origin". IE et Firefox ne le font pas et il n'est pas clair s'ils le feront jamais).

Dans cet esprit: quelle est la meilleure façon de se protéger contre les attaques CSRF sur les formulaires de connexion?

[~ # ~] update [~ # ~] : Je cherche une solution RESTful, donc idéalement je veux éviter de stocker l'état côté serveur par utilisateur. Cela est particulièrement vrai pour les utilisateurs non authentifiés. Si c'est impossible, je renoncerai évidemment à cette exigence.

34
Gili

Avec des cookies anonymes

Si vous êtes heureux de générer des jetons sécurisés qui sont définis comme des cookies d'utilisateurs anonymes, mais pas de les stocker côté serveur, vous pouvez simplement double soumettre les cookies .

par exemple. Utilisateur légitime:

  1. Un utilisateur ne navigue pas sur la page de connexion, reçoit un cookie qui est envoyé au navigateur.
  2. Un utilisateur ne se connecte pas et le navigateur envoie le cookie comme en-tête et comme valeur de formulaire masquée.
  3. L'utilisateur est maintenant connecté.

L'attaquant ne peut pas abuser de ce qui se produit maintenant:

  1. L'attaquant crée un compte Host sur le domaine de confiance
  2. L'attaquant falsifie une demande de connexion dans le navigateur de la victime avec les informations d'identification de ce compte hôte Cependant, l'attaquant n'a pas accès à la valeur de cookie de la victime et ne peut pas la forger en tant que jeton CSRF dans le corps de la demande. L'attaque échoue.

Même si votre site n'est accessible que via HTTPS et que vous définissez correctement le Secure Flag , cette approche doit être prise en compte car un attaquant pourrait potentiellement MiTM n'importe connexion de la victime à n'importe quel site Web HTTP (si l'attaquant est bien placé bien sûr), redirigez-les vers votre domaine via HTTP, qui est également MiTM'd, puis définissez le valeur de cookie requise. Ce serait une attaque Fixation de session . Pour éviter cela, vous pouvez afficher la valeur du cookie dans l'en-tête et le champ de formulaire masqué tous fois cette page (de connexion) est chargée (via HTTPS) plutôt que de réutiliser une valeur de cookie déjà définie. En effet, bien qu'un navigateur puisse définir l'indicateur sécurisé, il enverra toujours des cookies sans l'indicateur sécurisé via une connexion HTTPS, et le serveur ne pourra pas dire si l'indicateur sécurisé a été défini. (Les attributs de cookie tels que l'indicateur sécurisé ne sont visibles que lorsque le cookie est défini, pas lorsqu'il est lu. La seule chose que le serveur peut voir est le nom et la valeur du cookie.) Implémentation HSTS serait une bonne option de protection dans les navigateurs pris en charge.

Il est conseillé de définir X-Frame-Options pour empêcher une attaque de détournement de clic de réparation de l'interface utilisateur (sinon l'attaquant pourrait éventuellement utiliser la fonctionnalité du site pour pré-remplir son nom d'utilisateur et son mot de passe en attendant que l'utilisateur clique dessus et les soumette) avec la valeur CSRF).

Sans cookies anonymes

Si vous ne souhaitez pas définir de cookies pour les utilisateurs anonymes (qui peuvent alors soupçonner qu'ils sont suivis côté serveur), l'approche suivante peut être utilisée à la place: Un formulaire de connexion à plusieurs étapes.

La première étape est la combinaison username/mot de passe habituelle.

Une fois le formulaire soumis, il redirige vers un autre formulaire. Ce formulaire est protégé par un cookie de jeton d'authentification intermédiaire spécial et un jeton CSRF. L'authentification ici permettra uniquement de soumettre l'authentification de deuxième étape, mais ne permettra aucune autre action sur le compte (sauf éventuellement une déconnexion complète). Cela permettra au jeton CSRF d'être associé et utilisé par ce compte d'utilisateur uniquement sur cette session intermédiaire.

Maintenant, ce n'est que lorsque ce formulaire est soumis, y compris le cookie de jeton et la valeur de formulaire caché CSRF, que l'utilisateur est entièrement authentifié avec le domaine. Tout attaquant tentant une attaque CSRF ne pourra pas récupérer le jeton CSRF et sa tentative de connexion complète échouera.

Le seul inconvénient est que l'utilisateur devra cliquer manuellement pour terminer la connexion, ce qui peut être une expérience utilisateur maladroite. Il est conseillé de définir X-Frame-Options pour éviter que cela ne soit utilisé en combinaison avec une attaque de détournement de clic de réparation de l'interface utilisateur. Toute soumission automatique avec JavaScript serait bénéfique pour l'attaquant et entraînerait éventuellement le succès de son attaque, donc pour le moment je ne peux voir qu'un clic manuel de l'utilisateur travaillant.

Cela se jouerait maintenant comme ceci:

  1. L'attaquant crée un compte Host sur le domaine de confiance
  2. L'attaquant falsifie une demande de connexion dans le navigateur de la victime avec les informations d'identification de ce compte hôte , mais il ne peut pas passer la deuxième étape pour devenir entièrement authentifié
  3. L'attaquant incite la victime à utiliser le site de confiance - mais comme ils ne sont pas entièrement authentifiés, le site se comportera comme si l'utilisateur n'était pas authentifié
21
SilverlightFox

Donc une exigence légèrement niche, mais bon un CSRF valide. Il y a quelques choix sur la façon de résoudre ce problème qui me vient à l'esprit

  • Techniques anti-automatisation standard comme un CAPTCHA. Bien sûr, ce n'est pas la solution la plus conviviale, mais elle peut aider à atténuer d'autres attaques en même temps.
  • Avoir un jeton Anti-CSRF standard qui est lié aux informations fournies par le client et qui est disponible en pré-authentification. Une option évidente serait de le lier à l'adresse IP source. Ce n'est pas parfait (les systèmes derrière les mandataires auraient la même adresse) mais réduiraient un peu le risque. Une autre option serait de lier le jeton à des identités de navigateur spécifiques. Si vous regardez Panopticlick vous pouvez voir que les navigateurs fournissent des informations d'identification afin qu'il soit possible de créer une empreinte digitale basée sur cela et d'émettre un jeton Anti-CSRF pour chaque empreinte digitale qui contacte le site. Encore une fois pas parfait mais rend l'attaque plus difficile à exécuter.
4
Rory McCune

Je voudrais proposer une variante du Encrypted Token Pattern qui fonctionne comme suit: Lorsqu'un client demande une page HTML nécessitant une protection CSRF ...

  1. Le serveur vérifie l'existence d'un cookie sessionId. S'il est manquant, le serveur définit un nouveau cookie HttpOnly contenant une valeur pseudo-aléatoire cryptographiquement forte. Notez que cette valeur n'est pas stockée sur le serveur mais elle protège toujours contre la connexion CSRF (un attaquant ne peut pas s'authentifier sans passer par le formulaire de connexion).
  2. Si l'utilisateur est déconnecté, renvoyez une page HTML qui déclenche l'authentification pour les opérations dangereuses. Revenez à l'étape 1.
  3. Si l'utilisateur est connecté, le serveur chiffre [sessionId + nonce] à l'aide d'une clé secrète et incorpore la valeur (que nous appellerons csrfToken) dans le fichier HTML. Peu importe où csrfToken est intégré, tant que la fonction Formulaire ou Javascript faisant la demande peut y accéder. nonce est une valeur pseudo-aléatoire cryptographiquement forte utilisée pour empêcher les attaques par force brute sur la clé secrète, mais n'est pas utilisée pendant le processus de validation.
  4. Les formulaires envoient csrfToken en utilisant un champ caché du même nom. Les fonctions Javascript soumettent csrfToken à l'aide d'un en-tête de demande personnalisé nommé csrf-token.
  5. Le serveur déchiffre csrfToken et compare sa valeur à sessionId. Si les deux ne correspondent pas, le serveur renvoie 401 Unauthorized et déclenche l'authentification.
2
Gili

Vous pouvez appliquer n'importe laquelle des techniques anti-CSRF standard, que ce soit le modèle de jeton de synchronisation ou les cookies de double soumission. Le premier est généralement plus sécurisé, car les cookies peuvent être remplacés par des sous-domaines.

Vous avez affirmé que le modèle de jeton de synchroniseur ne fonctionne qu'après l'authentification, mais ce n'est pas le cas. Un attaquant n'a pas accès au token d'un utilisateur, que l'utilisateur soit authentifié ou non.

Bien sûr, l'attaquant peut visiter la page de connexion elle-même et obtenir un jeton anti-CSRF valide. Mais ce jeton niquement fonctionne pour l'attaquant. Si la victime fait une demande, le jeton n'est pas accepté, car il n'est pas présent dans la session de la victime. En fait, la session sera entièrement vide à la première demande.

0
Fleche