Génération de jeton CSRF

Ceci est une question sur la génération de jetons CSRF.

Habituellement, je voudrais générer un jeton basé sur un élément 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 en l’absence de données utilisateur uniques. 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 de hachage dans la demande? Exemple de pseudocode pour générer le jeton et l’intégrer:

var $ssortingngToHash = random() var $csrfToken = hash($ssortingngToHash + $mySecretKey) click me 

Exemple de validation côté serveur du jeton CSRF

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

La chaîne utilisée dans le hachage serait différente à chaque demande. Tant qu’il était inclus dans chaque requête, la validation du jeton CSRF pouvait se poursuivre. Comme il est nouveau à chaque demande et intégré uniquement dans la page, l’access externe au jeton ne serait pas disponible. La sécurité du jeton appartient alors à $ mySecretKey, qui n’est connue que de moi.

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

Merci

Y a-t-il une raison pour laquelle je ne peux pas inclure la chaîne de hachage dans la demande?

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 ailleurs empêche une page d’être autonome.

Si vous incluez la chaîne dans le hachage de la requête, la requête est autonome, donc tout attaquant doit copier le formulaire, car ils ont les deux parties du jeton, et il n’y a donc pas de protection.

Même en le mettant dans l’URL du formulaire, cela signifie qu’il est autonome, l’attaquant copie simplement le formulaire et l’URL de soumission.

Essayez base64_encode(openssl_random_pseudo_bytes(16)) . https://github.com/codeguy/php-the-right-way/issues/272#issuecomment-18688498 et je l’ai utilisé pour mon exemple de formulaire dans https://gist.github.com/mikaelz/5668195

CSRF jeton destiné à empêcher les modifications de données (involontaires), qui sont généralement appliquées aux requêtes POST.

Par conséquent, vous devez inclure un jeton CSRF pour chaque demande qui modifie des données (requête GET ou POST).

Ma question concerne la génération de jetons en l’absence de données utilisateur uniques. 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.

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

Modifier:

Considérez l’événement suivant:

Vous vous êtes connecté à votre compte facebook, puis vous êtes entré sur un site Web arbitraire.

Sur ce site Web, vous soumettez un formulaire qui indique à votre navigateur d’envoyer une demande POST à ​​votre compte facebook.

Cette demande POST peut modifier votre mot de passe ou append un commentaire, car l’application Facebook vous a reconnu comme utilisateur enregistré et connecté. (sauf s’il existe un autre mécanisme de blocage, comme CAPTCHA)

Vous avez simplement besoin du même “jeton” dans l’URL / formulaire et dans le cookie. Cela signifie que votre page pourrait définir le cookie de jeton comme il le souhaite (de préférence une valeur aléatoire) par JavaScript, puis simplement transmettre la même valeur à toutes les requêtes envoyées à votre serveur (en tant que URI? Param ou form- champ). Il n’est pas nécessaire que votre serveur génère le cookie.

Ceci est sûr tant que le navigateur n’autorise pas les pages d’un domaine à modifier / lire les cookies pour d’autres domaines, et cela est supposé être assez sécurisé aujourd’hui.

Le fait que votre serveur génère le jeton suppose que ce jeton peut être transmis en toute sécurité à votre navigateur sans être détecté par aucune tentative CSRF (pourquoi prendre le risque?). Bien que vous puissiez mettre plus de logique dans un jeton généré par un serveur, mais pour empêcher la fonction CSRF, il n’est pas nécessaire.

(Si je me trompe ici s’il vous plaît faites le moi savoir)

Je pense que la meilleure idée de faire un hash basé sur HMAC, c’est-à-dire de faire un hash encrypté par un mot de passe cette séquence: username + user_id + timestamp. Chaque demande de hachage doit être différente, l’horodatage doit être si vous ne voulez pas relire simplement le hachage en attaque.

Je veux dire que votre approche fonctionne, car l’attaque CSRF est l’attaquant qui utilise le navigateur de la victime pour créer un statut connecté, pourquoi peuvent-ils le faire? car la plupart des serveurs, le contrôle de session est basé sur un identifiant de session dans un cookie et un cookie est un élément de données qui sera automatiquement associé à une requête HTTP envoyée au serveur.

Il y a donc deux facteurs clés pour défendre la CSRF

  1. Générez un jeton de challenge et exigez que le client le transmette au serveur sans passer par un cookie, que ce soit le paramètre URL ou le formulaire POST.
  2. Gardez le jeton sécurisé comme vous l’avez fait avec l’ID de session, par exemple, en utilisant SSL.

Je recommande de lire le CSRF Prevention Cheat Sheet

Il existe plusieurs implémentations de jeton CSRF. L’essentiel est de savoir si ce jeton csrf est généré côté client ou côté serveur. Parce que l’implémentation change radicalement pour ces deux scénarios et pour l’entropie du jeton.

Côté serveur, SecureRandom est la méthode privilégiée, mais dans votre cas, vous souhaitez générer le jeton CSRF avant l’identification de tout utilisateur, window.crypto fournit cette fonctionnalité qui vous permet de générer une chaîne suffisamment incontournable pour le jeton CSRF.

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