Question Comprendre le jeton d'authenticité Rails


Je suis confronté à quelques problèmes concernant Authenticity Token in Rails, comme je l'ai plusieurs fois maintenant.

Mais je ne veux vraiment pas résoudre ce problème et continuer. J'aimerais vraiment comprendre le jeton Authenticité. Eh bien, ma question est, avez-vous une source complète d'informations sur ce sujet ou souhaitez-vous passer votre temps à expliquer dans les détails ici?


877
2018-06-02 20:01


origine


Réponses:


Ce qui se produit

Lorsque l'utilisateur affiche un formulaire pour créer, mettre à jour ou détruire une ressource, l'application Rails crée un authenticity_token, stocke ce jeton dans la session et le place dans un champ masqué dans le formulaire. Lorsque l'utilisateur soumet le formulaire, Rails recherche le authenticity_token, le compare à celui stocké dans la session, et si elles correspondent à la demande est autorisé à continuer.

Pourquoi ça arrive

Puisque le jeton d'authenticité est stocké dans la session, le client ne peut pas connaître sa valeur. Cela empêche les utilisateurs de soumettre des formulaires à une application Rails sans afficher le formulaire dans cette application. Imaginez que vous utilisez le service A, vous vous êtes connecté au service et tout va bien. Maintenant, imaginez que vous êtes allé utiliser le service B, et vous avez vu une image que vous aimez, et appuyez sur l'image pour voir une plus grande taille de celui-ci. Maintenant, si un code malveillant était présent sur le service B, il peut envoyer une demande au service A (auquel vous êtes connecté) et vous demander de supprimer votre compte, en envoyant une demande à http://serviceA.com/close_account. C'est ce qu'on appelle CSRF (Cross-Request Forgery).

Si le service A utilise des jetons d'authenticité, ce vecteur d'attaque n'est plus applicable, car la demande du service B ne contiendra pas le bon jeton d'authenticité et ne sera pas autorisée à continuer.

Documents d'API décrit les détails sur la balise META:

La protection CSRF est activée avec protect_from_forgery méthode,   qui vérifie le jeton et réinitialise la session si elle ne correspond pas   était attendu. Un appel à cette méthode est généré pour les nouveaux Rails   applications par défaut.   Le paramètre de jeton est nommé authenticity_token par défaut. Le nom   et la valeur de ce jeton doit être ajoutée à chaque mise en page qui rend   formulaires en incluant csrf_meta_tags dans la tête HTML.

Remarques

Gardez à l'esprit que Rails ne vérifie que les méthodes non-idempotentes (POST, PUT / PATCH et DELETE). Les requêtes GET ne sont pas vérifiées pour le jeton d'authenticité. Pourquoi? car la spécification HTTP indique que les requêtes GET sont idempotentes et devraient ne pas créer, altérer ou détruire des ressources sur le serveur, et la requête devrait être idempotent (si vous exécutez la même commande plusieurs fois, vous devriez obtenir le même résultat à chaque fois).

De plus, la mise en œuvre réelle est un peu plus compliquée que celle définie au début, assurant une meilleure sécurité. Rails n'émet pas le même jeton stocké avec chaque formulaire. Il ne génère et ne stocke pas non plus de jeton différent à chaque fois. Il génère et stocke un hachage cryptographique dans une session et émet de nouveaux jetons cryptographiques, qui peuvent être comparés à ceux stockés, chaque fois qu'une page est rendue. Voir request_forgery_protection.rb.

Cours

Utilisation authenticity_token pour protéger vos méthodes non idempotentes (POST, PUT / PATCH et DELETE). Veillez également à ne pas autoriser les demandes GET susceptibles de modifier les ressources sur le serveur.


MODIFIER: Vérifier le commentaire de @erturne concernant les requêtes GET étant idempotentes. Il l'explique mieux que moi ici.


1371
2017-10-15 11:52



Le jeton d'authenticité est conçu pour que vous sachiez que votre formulaire est envoyé depuis votre site Web. Il est généré à partir de la machine sur laquelle il s'exécute avec un identifiant unique que seule votre machine peut connaître, ce qui permet d'éviter les attaques de falsification de requêtes intersites.

Si vous avez simplement des difficultés avec les rails qui refusent l'accès au script AJAX, vous pouvez utiliser

<%= form_authenticity_token %>

pour générer le jeton correct lorsque vous créez votre formulaire.

Vous pouvez en lire plus à ce sujet dans le Documentation.


129
2018-06-02 20:16



Qu'est-ce que CSRF?

Le jeton d'authenticité est une contre-mesure à la contrefaçon de demande inter-site (CSRF). Qu'est-ce que CSRF, demandez-vous?

C'est un moyen qu'un pirate peut potentiellement pirater des sessions sans même connaître les jetons de session.

Scénario:

  • Visitez le site de votre banque, connectez-vous.
  • Visitez ensuite le site de l'attaquant (par exemple, une annonce sponsorisée provenant d'une organisation non approuvée).
  • La page de l'attaquant inclut un formulaire avec les mêmes champs que le formulaire "Transfert de fonds" de la banque.
  • L'attaquant connaît vos informations de compte et a pré-rempli des champs de formulaire pour transférer de l'argent de votre compte vers le compte de l'attaquant.
  • La page de l'attaquant inclut Javascript qui soumet le formulaire à votre banque.
  • Lorsque le formulaire est envoyé, le navigateur inclut vos cookies pour le site de la banque, y compris le jeton de session.
  • La banque transfère de l'argent au compte de l'attaquant.
  • Le formulaire peut être dans un iframe invisible, donc vous ne savez jamais que l'attaque s'est produite.
  • C'est ce qu'on appelle Cross-Site Request Forgery (CSRF).

Solution CSRF:

  • Le serveur peut marquer des formulaires provenant du serveur lui-même
  • Chaque formulaire doit contenir un jeton d'authentification supplémentaire en tant que champ masqué.
  • Le jeton doit être imprévisible (l'attaquant ne peut pas le deviner).
  • Le serveur fournit un jeton valide dans les formulaires de ses pages.
  • Le serveur vérifie le jeton lorsqu'il est posté, rejette les formulaires sans jeton approprié.
  • Exemple de jeton: identifiant de session chiffré avec la clé secrète du serveur.
  • Rails génère automatiquement de tels jetons: consultez le champ de saisie authenticity_token sous chaque forme.

77
2018-06-13 01:54



Exemple d'attaque minimale qui serait évitée

Sur mon site evil.com Je vous convaincs de soumettre le formulaire suivant:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Si vous êtes connecté à votre banque via des cookies de session, les cookies seront envoyés et le transfert sera effectué sans même que vous le sachiez.

C'est là que le jeton CSRF entre en jeu:

  • avec la réponse GET qui a renvoyé le formulaire, Rails envoie un paramètre caché aléatoire très long
  • lorsque le navigateur fait la requête POST, il envoie le paramètre et le serveur ne l'accepte que s'il correspond

Donc le formulaire sur un navigateur authentique ressemblerait à ceci:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Ainsi, mon attaque échouerait, car elle n'envoyait pas authenticity_token paramètre, et il n'y a aucun moyen que je puisse l'avoir deviné puisque c'est un nombre aléatoire énorme.

Cette technique de prévention est appelée Modèle de jeton de synchronisation.

Le modèle de jeton du synchroniseur fonctionne en raison de Politique d'origine identique: si je pouvais faire une demande XHR GET à votre banque de evil.com, et lire le résultat, je serais capable de simplement lire un jeton, puis faire la demande plus tard. Je l'ai expliqué plus en détail à: https://security.stackexchange.com/a/72569/53321

Je vous recommande fortement de lire le guide OWASP, sur ceci et toute autre question de sécurité.

Comment Rails envoie les jetons

Couvert à: Rails: Comment fonctionne csrf_meta_tag?

Fondamentalement:

  • Les assistants HTML aiment form_tag ajouter un champ caché au formulaire pour vous si ce n'est pas un formulaire GET

  • AJAX est traité automatiquement par jquery-ujs, qui lit le jeton de la meta éléments ajoutés à votre en-tête par csrf_meta_tags (présent dans le modèle par défaut), et l'ajoute à toute demande faite.

    uJS tente également de mettre à jour le jeton dans des formulaires dans des fragments mis en cache obsolètes.

Autres approches de prévention


36
2017-11-12 20:30



le Authenticity Token est la méthode des rails à prévenir  'contrefaçon de requête intersite (CSRF ou XSRF)'.

Pour faire simple, il s'assure que les requêtes PUT / POST / DELETE (méthodes pouvant modifier le contenu) de votre application web proviennent du navigateur du client et non d'un tiers (un attaquant) ayant accès à un cookie créé du côté client.


35
2018-06-02 20:17



depuis Authenticity Token est si important, et dans Rails 3.0+, vous pouvez utiliser

 <%= token_tag nil %>

créer

<input name="authenticity_token" type="hidden" value="token_value">

nulle part


32
2017-08-01 05:12



Attention, le mécanisme de jeton d'authenticité peut entraîner des conditions de concurrence si vous avez plusieurs demandes simultanées provenant du même client. Dans cette situation, votre serveur peut générer plusieurs jetons d'authenticité alors qu'il ne devrait y en avoir qu'un, et le client recevant le jeton précédent dans un formulaire échouera lors de la prochaine requête car le jeton de cookie de session a été remplacé. Il y a un commentaire sur ce problème et une solution pas entièrement triviale ici: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


25
2017-08-30 23:52



Le jeton d'authenticité est utilisé pour empêcher les attaques CSFF (Cross-Site Request Forgery). Pour comprendre le jeton d'authenticité, vous devez d'abord comprendre les attaques CSRF.

CSRF

Supposons que vous êtes l'auteur de bank.com. Vous avez un formulaire sur votre site qui est utilisé pour transférer de l'argent sur un autre compte avec une requête GET:

enter image description here

Un hacker pourrait simplement envoyer une requête HTTP au serveur en disant GET /transfer?amount=$1000000&account-to=999999, droite?

enter image description here

Faux. L'attaque des pirates ne fonctionnera pas. Le serveur pensera fondamentalement?

Huh? Qui est ce type qui essaie d'initier un transfert? Ce n'est pas le propriétaire du compte, c'est certain.

Comment le serveur le sait-il? Parce qu'il n'y a pas session_id cookie authentifiant le demandeur.

Lorsque vous vous connectez avec votre nom d'utilisateur et votre mot de passe, le serveur définit un session_id cookie sur votre navigateur. De cette façon, vous n'avez pas à authentifier chaque demande avec votre nom d'utilisateur et votre mot de passe. Lorsque votre navigateur envoie le session_id cookie, le serveur sait:

Oh, c'est John Doe. Il s'est connecté avec succès il y a 2.5 minutes. Il est bon d'y aller.

Un pirate pourrait penser:

Hmm. Une requête HTTP normale ne fonctionnera pas, mais si je pouvais obtenir ma main sur ce session_id cookie, je serais d'or.

Le navigateur des utilisateurs a un ensemble de cookies pour le bank.com domaine. Chaque fois que l'utilisateur fait une demande au bank.com domaine, tous les cookies sont envoyés. Incluant le session_id biscuit.

Donc, si un pirate pouvait obtenir toi pour faire la demande GET qui transfère de l'argent sur son compte, il aurait du succès. Comment pourrait-il vous tromper pour le faire?  Avec Cross Site Request Forgery.

C'est assez simple, en fait. Le hacker pourrait juste vous amener à visiter son site Web. Sur son site Web, il pourrait avoir la balise d'image suivante:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Lorsque le navigateur des utilisateurs rencontre cette balise d'image, une requête GET est envoyée à cette URL. Et puisque la requête vient de son navigateur, il va envoyer avec lui tous les cookies associés à bank.com. Si l'utilisateur s'est récemment connecté à bank.com... la session_id cookie sera défini, et le serveur pensera que l'utilisateur a l'intention de transférer 1 000 000 $ au compte 999999!

enter image description here

Eh bien, ne visitez pas les sites dangereux et tout ira bien.

Cela ne suffit pas. Que se passe-t-il si quelqu'un publie cette image sur Facebook et qu'elle apparaît sur votre mur? Que faire s'il est injecté dans un site que vous visitez avec une attaque XSS?

Ce n'est pas si grave. Seules les requêtes GET sont vulnérables.

Pas vrai. Un formulaire qui envoie une requête POST peut être généré dynamiquement. Voici l'exemple de la Rails Guide sur la sécurité:

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Jeton d'authenticité

Quand ton ApplicationController a ceci:

protect_from_forgery with: :exception

Ce:

<%= form_tag do %>
  Form contents
<% end %>

Est compilé dans ceci:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

En particulier, ce qui suit est généré:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

Pour se protéger contre les attaques CSRF, si Rails ne voit pas le jeton d'authenticité envoyé avec une requête, il ne considérera pas la demande comme sûre.

Comment un attaquant est-il supposé savoir ce qu'est ce jeton? Une valeur différente est générée aléatoirement chaque fois que le formulaire est généré:

enter image description here

Une attaque XSS (Cross Site Scripting) - voilà comment. Mais c'est une vulnérabilité différente pour un jour différent.


23
2018-04-14 04:33



Méthodes Où authenticity_token est requis

authenticity_token est requis dans le cas de méthodes idempotentes comme post, put et delete, Parce que les méthodes Idempotent affectent les données.

Pourquoi est-il nécessaire

Il est nécessaire d'empêcher les mauvaises actions. authenticity_token est stocké en session, chaque fois qu'un formulaire est créé sur des pages web pour créer ou mettre à jour des ressources puis qu'un jeton d'authenticité est stocké dans un champ caché et qu'il est envoyé avec le formulaire sur le serveur. Avant d'exécuter l'action, l'utilisateur envoyé authenticity_token est contre-vérifié avec authenticity_token stocké en session. Si authenticity_token est le même que le processus est continuer sinon il n'effectue pas d'actions.


8
2018-02-26 11:13



Qu'est-ce qu'un authentication_token?

Il s'agit d'une chaîne aléatoire utilisée par l'application Rails pour s'assurer que l'utilisateur demande ou exécute une action depuis la page de l'application, et non depuis une autre application ou un autre site.

Pourquoi un authentication_token est-il nécessaire?

Pour protéger votre application ou votre site contre les falsifications de requêtes intersites.

Comment ajouter un authentication_token à un formulaire?

Si vous générez un formulaire en utilisant form_for tag, un authentication_token est automatiquement ajouté sinon vous pouvez utiliser <%= csrf_meta_tag %>.


3
2017-07-22 02:02