Ruby on Rails nous offre tellement de mécanismes d’abstraction qu’on en oublie parfois les bases.
Dans l’idée de notre article sur le fonctionnement des sessions, découvrons aujourd’hui pourquoi et comment fonctionne l’authenticity token.
L’objectif est de prévenir les attaques de type Cross site request forgery.
Le fonctionnement est simple, vous vous authentifiez sur votre application A.
Sur une autre application B vous utilisez un formulaire ou un lien qui pointe en fait vers une action de l’application A sans que vous le sachiez.
En l’absence de mécanisme de contrôle vous pouvez modifier voire supprimer des resources sur l’application A sans même vous en rendre compte.
En tant qu’utilisateur il y a un premier de niveau de sécurité à apporter ; il s’agit d’éviter de rester connecter sur des services qu’on n’est pas entrain d’utiliser.
En somme dès que j’arrête d’utiliser un service je me déconnecte.
Côté développeur il faut absolument éviter de proposer des actions suceptibles de modifier des ressources sous forme de lien ou de form en GET, car dans ce cas les token ne vous protégeront pas comme nous le verrons ci dessous.
Au delà du GET on a déjà un premier volet de sécurité concernant la politique de sécurité des navigateurs pour les appels en AJAX depuis un autre domaine.
Voir à ce sujet les commentaires de l’article sur rails 4 à propos de CORS.
Quand une vue avec un formulaire est rendue, Rails y ajoute un token aléatoire dans un champ caché, et dans la session de l’utilisateur.
À la soumission du formulaire, un contrôle sera fait pour s’assurer que le token est soumis et que sa valeur correspond à celle de la session.
Le code de génération du token est très simple, il se trouve dans ActionPack:
# Sets the token value for the current session.
def form_authenticity_token
session[:_csrf_token] ||= SecureRandom.base64(32)
end
La vérification de la requête est elle aussi basique, Rails va juste vérifier qu’il ne s’agit pas d’une requête GET, HEAD, que la protection est activée et que le token est présent dans les params ou dans les headers, dans le cas d’une requête venant d’un autre domaine.
def verified_request?
!protect_against_forgery? || request.get? || request.head? ||
form_authenticity_token == params[request_forgery_protection_token] ||
form_authenticity_token == request.headers['X-CSRF-Token']
end
Voilà tout pour cet article sur le fonctionnement des tokens.
On trouve trop souvent des articles ou des fils de discussion qui recommandent de désactiver la protection au moindre souci (souvent dans le cas d’utilisation conjointe avec AJAX).
Ne faites pas ça, creusez vous la tête et fixez le problème plutôt que d’ouvrir des brèches de sécurité.
L’équipe Synbioz.
Libres d’être ensemble.