2009-11-26 9 views
37

Il s'agit d'une question sur la génération de jetons CSRF.Génération de jetons CSRF

Habituellement, je voudrais générer un jeton basé sur un morceau de données unique associé à la session de l'utilisateur, et haché et salé avec une clé secrète.

Ma question concerne la génération de jetons lorsqu'il n'y a PAS de données utilisateur uniques à utiliser. Aucune session n'est disponible, les cookies ne sont pas une option, l'adresse IP et les choses de cette nature ne sont pas fiables.

Y a-t-il une raison pour laquelle je ne peux pas inclure la chaîne dans le hachage dans le cadre de la requête? Exemple pseudocode pour générer le jeton et l'intégrer:

var $stringToHash = random() 
var $csrfToken = hash($stringToHash + $mySecretKey) 
<a href="http://foo.com?csrfToken={$csrfToken}&key={$stringToHash}">click me</a> 

Exemple validation côté serveur du jeton CSRF

var $stringToHash = request.get('key') 
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken') 

La chaîne à utiliser dans la table de hachage qui serait différent à chaque demande. Tant qu'elle était incluse dans chaque requête, la validation du jeton CSRF pouvait se poursuivre. Comme il s'agit d'une nouveauté sur chaque requête et uniquement intégrée dans la page, l'accès externe au jeton ne serait pas disponible. La sécurité du jeton tombe alors sur le $ mySecretKey étant connu seulement pour moi.

Est-ce une approche naïve? Est-ce que je manque une raison pour laquelle cela ne peut pas fonctionner?

Merci

+8

La solution proposée est vulnérable aux attaques par rejeu.Le même jeton et la même combinaison de touches fonctionneront indéfiniment. – Matthew

Répondre

2

CSRF jeton destinés à empêcher les modifications de données (non intentionnelles), qui sont généralement appliquées aux demandes POST. Par conséquent, vous devez inclure un jeton CSRF pour chaque requête qui modifie les données (demande GET ou POST).

Ma question est en ce qui concerne jetons de production quand il n'y a pas données utilisateur uniques à utiliser. Pas de sessions sont disponibles, les cookies ne sont pas une option , l'adresse IP et les choses de ce ne sont pas fiables.

Ensuite, créez simplement un ID utilisateur unique pour chaque visiteur. Inclure cet identifiant dans un cookie ou dans les URL (si les cookies sont désactivés).

Edit:

Tenir compte l'événement suivant:

Vous avez connecté à votre compte Facebook, puis est entré à un certain site Web arbitraire.

Dans ce site Web, il y a un formulaire que vous soumettez, qui indique à votre navigateur d'envoyer une requête POST à ​​votre compte facebook.

Cette requête POST peut changer votre mot de passe ou ajouter un commentaire, etc, parce que l'application facebook vous a reconnu comme un utilisateur enregistré & enregistré. (sauf s'il y a un autre mécanisme de blocage, comme CAPTCHA)

+0

L'ajout d'une partie du jeton à une URL et l'insertion de l'autre moitié dans le formulaire n'offrent aucune protection. – blowdart

+0

Désolé mais que voulez-vous dire? Je n'ai pas écrit ça ... – Dor

+0

Bien sûr que vous l'avez fait, "Inclure cet identifiant dans un cookie ou dans les URL (si les cookies sont désactivés)." - Vous dites de mettre l'identifiant dans l'URL, ce n'est tout simplement pas sécurisé. – blowdart

-4

CSRF utilise la session de l'utilisateur, donc, si vous n'en avez pas, il n'y a pas de CSRF.

+0

Bien que cette réponse ne soit pas utile du tout, elle est techniquement correcte. –

25

Y a-t-il une raison pour laquelle je ne peux pas inclure la chaîne dans le hachage dans le cadre de la requête?

Les jetons CSRF ont deux parties. Le jeton incorporé dans le formulaire, et un jeton correspondant ailleurs, que ce soit dans un cookie, stocké dans une session ou ailleurs. Cette utilisation d'ailleurs arrête une page étant autonome.

Si vous incluez la chaîne à hacher dans la requête, alors la requête est autonome, donc la copie du formulaire est tout ce qu'un attaquant doit faire, car il possède les deux parties du jeton, et donc aucune protection.

Même en le mettant sous la forme URL signifie qu'il est autonome, l'attaquant copie simplement le formulaire et l'URL de soumission.

+0

Vous devez vous rappeler que le jeton est stocké sur le serveur ... –

+14

Non. Une moitié pourrait être conservée en session, ou elle pourrait être abandonnée via un cookie. Il n'a pas du tout besoin d'être stocké sur le serveur, il est généralement basé sur des cookies, ce qui vous évite de devoir compter sur des sessions d'activation. – blowdart

+0

Selon OWASP, ceci est seulement une * atténuation * appelée "double submit cookies" https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Double_Submit_Cookies – zb226

1

Vous avez simplement besoin du même "jeton" dans l'URL/le formulaire et dans le cookie. Cela signifie que votre page pourrait définir le cookie de jetons comme il le souhaite (de préférence une valeur aléatoire) par JavaScript, puis transmettre la même valeur dans toutes les requêtes envoyées à votre serveur (sous la forme d'un URI? champ). Pas besoin d'avoir votre serveur générant le cookie. Ceci est sûr aussi longtemps que nous croyons que le navigateur n'autorise pas les pages d'un domaine à éditer/lire les cookies pour d'autres domaines, et cela est supposé être assez sûr aujourd'hui. Si votre serveur génère le jeton, il est supposé que ce jeton peut être transmis en toute sécurité à votre navigateur sans être détecté par les tentatives de CSRF (pourquoi prendre le risque?). Bien que vous pourriez mettre plus de logique dans un jeton généré par le serveur, mais pour éviter CSRF, il n'y a pas besoin.

(Si je me trompe s'il vous plaît laissez-moi savoir)

0

Je pense que la meilleure idée de faire de hachage basée sur HMAC, à savoir faire de hachage crypté par un mot de passe cette séquence: nom d'utilisateur + user_id + horodatage. Chaque requête du hachage doit être différente, l'horodatage doit être si vous ne voulez pas simplement rejouer le hachage en attaque.

0

Je veux dire que votre approche fonctionne, parce que l'attaque CSRF L'attaquant utilise-t-il le navigateur de la victime pour forger un statut connecté, pourquoi peut-il le faire? parce que sur la plupart des serveurs, la vérification de session est basée sur un SessionID dans un cookie, et un cookie est une donnée qui sera automatiquement attachée à une requête HTTP envoyée au serveur.

Par conséquent, il y a deux facteurs clés pour la défense CSRF

  1. Générer un jeton de défi, et exigent le client de le transmettre au serveur d'une manière non-cookies, soit param ou sous forme POST URL est ok.
  2. Conservez le jeton en toute sécurité comme vous l'avez fait pour le SessionID, par exemple, en utilisant SSL.

Je recommande la lecture CSRF Prevention Cheat Sheet

Questions connexes