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:
- L'attaquant crée un compte Host sur le domaine de confiance
- L'attaquant falsifie une demande de connexion dans le navigateur de la victime avec les informations d'identification de ce compte hôte
- 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
- 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.
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:
L'attaquant ne peut pas abuser de ce qui se produit maintenant:
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).
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:
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
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 ...
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).[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.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
.csrfToken
et compare sa valeur à sessionId
. Si les deux ne correspondent pas, le serveur renvoie 401 Unauthorized
et déclenche l'authentification.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.