Le CSRF : falsification de requête inter-site
Imaginez que votre banque accepte un ordre de virement dès qu’il porte votre tampon, sans vérifier qui le dépose. Quelqu’un qui sait où vous avez l’habitude de laisser votre tampon pourrait glisser un ordre à votre insu. C’est l’idée du CSRF (Cross-Site Request Forgery) : amener le navigateur d’un utilisateur connecté à envoyer, sans qu’il le sache, une requête que le site considérera comme légitime. Ici, aucun code n’est injecté dans le site : on exploite la confiance qu’il accorde au navigateur.
Rappel légal
Provoquer une action au nom d’un utilisateur, qu’il s’agisse d’un virement, d’un changement d’adresse ou d’un message, est une atteinte grave : sur un site réel sans autorisation écrite, c’est une infraction (articles 323-1 à 323-3-1 du Code pénal). Cette leçon décrit le mécanisme pour apprendre à le détecter et à s’en prémunir. Les essais se font avec deux comptes de test, dans DVWA, Juice Shop ou la PortSwigger Web Security Academy.
Le mécanisme, en clair
Quand vous êtes connecté à un site, votre navigateur ajoute automatiquement le cookie de session à toute requête vers ce site, quelle que soit la page d’où part la requête. C’est pratique, mais cela crée un risque :
- Vous êtes connecté à un site légitime (A) et votre session est active.
- Vous visitez ensuite une autre page (B), préparée par un tiers.
- Cette page B fait envoyer à votre navigateur une requête vers le site A (par un formulaire, une image, un script).
- Votre navigateur joint le cookie de session. Le site A reçoit une requête qui ressemble à s’y méprendre à une action volontaire de votre part, et l’exécute.
Le site A ne vérifie qu’une chose : « le cookie est-il valide ? ». Il ne vérifie pas : « cette requête vient-elle réellement de ma propre interface ? ».
Quelles actions sont à risque ?
Le CSRF ne vole pas de données : il fait faire des actions. Sont à risque les opérations qui modifient un état et qui ne demandent aucune confirmation supplémentaire :
- changer un mot de passe ou une adresse e-mail (puis récupérer le compte) ;
- effectuer un virement ou une commande ;
- modifier des droits, supprimer des données ;
- publier un contenu, envoyer un message.
L’attaquant ne voit généralement pas la réponse : il compte sur l’effet de l’action. Plus l’action est sensible et plus la victime est privilégiée (un administrateur), plus l’impact est grave.
Les conditions de la faille
Pour qu’un CSRF fonctionne, trois conditions doivent être réunies :
| Condition | Explication |
|---|---|
| Une action pertinente | Une opération qui change quelque chose d’intéressant |
| Une authentification par cookie | Le navigateur joint automatiquement le laissez-passer |
| Des paramètres prévisibles | Aucun élément secret que l’attaquant ne puisse connaître dans la requête |
La troisième condition est la clé de la défense : si la requête contient un élément secret et imprévisible lié à la session, l’attaquant ne peut pas la fabriquer.
Comment le détecter, sans rien attaquer
Le test de base se fait à l’aide de votre proxy et de deux comptes de test :
- Identifier une action sensible (le changement de mot de passe de DVWA, par exemple) et la capturer dans l’historique du proxy.
- Examiner la requête : contient-elle un jeton imprévisible (un champ du formulaire ou un en-tête personnalisé) ? Utilise-t-elle la méthode
GETpour modifier un état (très mauvais signe) ? Le cookie porte-t-il l’attributSameSite? - Se demander : tous les paramètres sont-ils connus ou devinables ? Si oui, la requête est forgeable.
- Vérifier le comportement du serveur en rejouant la requête depuis le module de rejeu sans le jeton, ou avec un jeton périmé : l’action est-elle quand même acceptée ?
Si le serveur accepte une requête sans jeton valide, le constat est établi : la requête est falsifiable. Vous n’avez pas besoin de construire de page piégée pour le prouver ; en audit, la démonstration via le rejeu suffit, et un éventuel exemple de page de preuve se fait uniquement dans le périmètre autorisé.
Les défenses
1. Le jeton anti-CSRF
Le serveur génère un jeton secret, aléatoire, lié à la session de l’utilisateur, l’inclut dans les formulaires et le vérifie à chaque requête qui modifie un état. Une page tierce ne peut pas deviner ce jeton, donc ne peut pas fabriquer une requête valide :
<form method="post" action="/profil/modifier">
<input type="hidden" name="jeton" value="VALEUR_ALEATOIRE_LIEE_A_LA_SESSION">
<input type="email" name="email">
<button type="submit">Enregistrer</button>
</form>
Côté serveur, la requête est rejetée si le jeton est absent, incorrect ou expiré. Bonnes pratiques : jeton long et aléatoire, vérification systématique, comparaison sûre, pas de jeton dans l’adresse, renouvellement à la connexion. Beaucoup de cadres de développement modernes proposent cette protection nativement : il faut simplement ne pas la désactiver.
2. L’attribut SameSite des cookies
Il indique au navigateur de ne pas joindre le cookie aux requêtes provenant d’autres sites (selon la valeur choisie). Les navigateurs récents appliquent par défaut une valeur raisonnable, mais on ne doit pas s’y fier aveuglément : déclarez-la explicitement. C’est une défense précieuse, à ajouter au jeton, pas à la place.
3. Les méthodes HTTP appropriées
Une requête GET doit être sans effet de bord (lecture seule). Toute modification passe par POST, PUT ou DELETE, avec vérification du jeton.
4. La vérification de l’origine
Le serveur peut contrôler les en-têtes Origin ou Referer et refuser les requêtes qui viennent d’un site inattendu. C’est une défense complémentaire utile.
5. La confirmation des actions sensibles
Pour les opérations critiques (changement de mot de passe, virement), redemander le mot de passe actuel ou un second facteur. Une requête forgée ne le contient pas.
Attention aux confusions
- XSS ≠ CSRF : le XSS injecte du code dans le site et peut lire des données ; le CSRF exploite un navigateur qui joint un cookie, sans injecter de code. Mais un XSS permet souvent de contourner une protection CSRF, car un script qui s’exécute sur le site peut lire le jeton. D’où l’importance de corriger les deux.
- « Mon site est en POST, donc il est protégé » : faux, un formulaire
POSTpeut aussi être soumis depuis une autre page. - « Une API avec jeton dans un en-tête n’est pas concernée » : souvent vrai, car le navigateur n’ajoute pas automatiquement un en-tête personnalisé ; mais l’authentification par cookie reste sensible.
Astuce
Dans DVWA, comparez le niveau bas (aucun jeton, changement de mot de passe par simple requête) et le niveau « impossible » (mot de passe actuel exigé + jeton). C’est la meilleure illustration de la défense en deux couches.
À vous de jouer
- Dans DVWA (niveau bas), capturez dans le proxy la requête de changement de mot de passe. Listez tous ses paramètres et dites lesquels sont secrets.
- Répondez : un tiers pourrait-il fabriquer cette requête ? Pourquoi ?
- Passez au niveau « impossible » : quels éléments supplémentaires voyez-vous dans la requête ?
- Rédigez le constat dans votre carnet, avec la correction proposée.
Voir une solution
Au niveau bas, la requête ne contient que le nouveau mot de passe et sa confirmation : aucun secret propre à la session. Un tiers pourrait donc la fabriquer, et le navigateur de la victime joindrait son cookie. Au niveau « impossible », la requête exige le mot de passe actuel et un jeton anti-CSRF, imprévisible pour un tiers. Constat type : « Le changement de mot de passe n’est protégé par aucun jeton ni confirmation. Impact : un utilisateur connecté qui visite une page piégée verrait son mot de passe changé. Gravité moyenne à élevée. Correction : jeton anti-CSRF, SameSite explicite, mot de passe actuel exigé. »
À retenir
- Le CSRF fait exécuter à un utilisateur connecté une action qu’il n’a pas voulue, en exploitant l’envoi automatique du cookie.
- Il vise les actions qui modifient un état ; l’attaquant ne voit pas forcément la réponse.
- Défense principale : jeton anti-CSRF imprévisible lié à la session, vérifié côté serveur.
- Compléments :
SameSite, méthodes HTTP adaptées, vérification deOrigin, confirmation des actions sensibles. - Un XSS peut contourner la protection CSRF : il faut corriger les deux.
Dernière leçon du chapitre : tromper l’œil de l’utilisateur plutôt que son navigateur, et les en-têtes qui nous protègent de bien des failles côté client.