Forge de requête Exploite l'authentification Bloqué par SameSite + tokens Mis à jour · Avril 2026

CSRF

Signification : Cross-Site Request Forgery · XSRF · session riding
Réponse rapide

Attaque applicative qui force un utilisateur authentifié à effectuer des actions non désirées sur un site où il est connecté, sans qu’il s’en rende compte. L’attaquant exploite le fait que le navigateur envoie automatiquement les cookies de session avec chaque requête vers le site cible, y compris quand la requête est initiée depuis un site malveillant.

En une phrase — Le CSRF force un utilisateur authentifié à exécuter une action à son insu sur un site où il est connecté. L'attaquant exploite le fait que le navigateur envoie automatiquement les cookies de session. Protection : tokens CSRF + attribut SameSite des cookies.
Catégorie OWASP
Sortie du Top 10 en 2017 grâce aux protections par framework
CWE
CWE-352 (Cross-Site Request Forgery)
Apparition publique
Article de Peter Watkins en 2001 ("Cross-Site Request Forgeries")
Protection principale
Tokens CSRF synchronisés + SameSite cookies
Tournant navigateur
Chrome 80 (2020) — SameSite=Lax par défaut

01 — DéfinitionQu'est-ce qu'un CSRF ?

Le CSRF (Cross-Site Request Forgery, parfois XSRF ou session riding) est une attaque applicative qui force un utilisateur authentifié à exécuter une action non désirée sur un site où il est connecté, à son insu.

Le principe en une image

Vous êtes connecté à votre banque en ligne dans un onglet. Dans un autre onglet, vous ouvrez un site piégé — forum compromis, email HTML malveillant, page gratuite trouvée via recherche. Ce site piégé contient du code caché qui envoie une requête vers votre banque :

<img src="https://ma-banque.com/virement?destinataire=attaquant&montant=5000" />

Votre navigateur charge l'image, donc émet la requête vers la banque. Comme vous êtes authentifié, le navigateur envoie automatiquement votre cookie de session. Du point de vue de la banque, la requête est indiscernable d'une action légitime. Le virement est effectué.

Pourquoi ça marche ?

Le CSRF exploite une propriété fondamentale du web : le navigateur envoie automatiquement les cookies associés à un domaine à chaque requête vers ce domaine, peu importe quel site a initié la requête. Sans protection explicite, le site cible ne peut pas distinguer :

  • Une action volontaire initiée depuis ses propres pages.
  • Une action forgée depuis un autre site, exploitant les cookies déjà présents.

Les trois conditions d'un CSRF exploitable

  • L'utilisateur doit être authentifié sur le site cible.
  • Le site cible doit utiliser l'authentification par cookies (sans vérification supplémentaire).
  • L'action doit avoir un effet de bord (transfert, changement de mot de passe, achat, modification de profil).

Conséquences typiques

  • Transferts d'argent : sur les banques vulnérables.
  • Changement de mot de passe ou d'email : pour prendre le contrôle du compte.
  • Changement d'adresse de livraison : pour détourner les commandes.
  • Modification de droits : ajout admin sur Wordpress, CMS, applications internes.
  • Achats non voulus : sur des sites e-commerce.
  • Publication de contenu : posts, commentaires au nom de la victime.
  • Abonnement/désabonnement : listes, services payants.
  • Propagation (CSRF worm) : rare mais possible si combiné avec du social.

Le nom « Cross-Site »

« Cross-Site » vient du fait que la requête forgée est initiée depuis un site différent du site cible. Le nom « session riding » utilisé historiquement capture bien la mécanique : l'attaquant « monte » sur la session existante de la victime.

Le CSRF est l'attaque qui montre que le navigateur est un peu trop complaisant par défaut : il envoie vos identifiants à chaque site qui les demande, même si la demande vient d'une source non liée. C'est une faille de conception du web des années 1990 que nous corrigeons progressivement depuis 20 ans.

02 — FonctionnementAnatomie d'une attaque CSRF

Scénario détaillé avec GET

Cas le plus simple et le plus dangereux : une action qui utilise GET.

Étape 1 — Reconnaissance

L'attaquant analyse le site cible et trouve qu'un transfert se fait via :

GET https://ma-banque.com/virement?destinataire=X&montant=Y

Étape 2 — Création du piège

L'attaquant crée une page web avec une image invisible :

<html>
  <body>
    Vous avez gagné !
    <img src="https://ma-banque.com/virement?destinataire=attaquant&montant=5000"
         width="0" height="0" />
  </body>
</html>

Étape 3 — Diffusion

L'attaquant diffuse le piège : email HTML, commentaire de blog, publicité sur un forum, message privé sur un réseau social, lien raccourci.

Étape 4 — Exécution

La victime, connectée à sa banque, ouvre la page piégée. Son navigateur essaie de charger l'image, ce qui envoie la requête GET à la banque avec son cookie de session. La banque exécute le virement.

Scénario avec POST

Plus courant aujourd'hui car les bonnes pratiques exigent POST pour les actions. L'attaquant utilise un formulaire auto-soumis :

<html>
  <body onload="document.forms[0].submit()">
    <form action="https://ma-banque.com/virement" method="POST">
      <input name="destinataire" value="attaquant">
      <input name="montant" value="5000">
    </form>
  </body>
</html>

La victime ouvre la page, le JavaScript soumet le formulaire automatiquement. Le navigateur envoie la requête POST avec les cookies de session.

Scénario avec JSON (API)

Plus complexe car le navigateur ne peut pas naturellement envoyer du JSON en cross-origin. Techniques :

  • Formulaire avec enctype=text/plain : contourne certaines protections si l'API accepte ce Content-Type.
  • fetch avec mode no-cors : dans certains cas l'API est exploitable même sans voir la réponse.
  • CORS mal configuré : Access-Control-Allow-Origin: * combiné avec credentials.

Vecteurs d'injection typiques

  • Sites compromis : un forum, un blog, un site d'actualités avec XSS persistante ou hébergement compromis.
  • Email HTML malveillant : même lu dans un webmail, les images externes se chargent souvent.
  • Publicité malveillante (malvertising) : réseaux publicitaires peu filtrés.
  • Messages privés sur réseaux sociaux qui rendent du HTML.
  • Applications tierces : widgets, plugins qui rendent du contenu utilisateur.
  • XSS sur un autre site : une XSS peut charger un payload CSRF contre un site tiers.

Variantes et extensions

CSRF en GET

Ancien cas — banques, CMS qui utilisaient GET pour actions. Aujourd'hui proscrit par les standards (RFC 7231 demande que GET soit safe et idempotent). Reste possible sur applications legacy.

CSRF stored

Quand une XSS stored permet d'injecter du code dans une page du site cible lui-même, le même-origine permet d'émettre des requêtes contournant les protections classiques. Frontière floue avec XSS.

Login CSRF

Forcer la victime à se connecter avec les identifiants de l'attaquant. La victime utilise ensuite « son » compte sans se rendre compte que c'est celui de l'attaquant qui récupèrera toutes les données saisies (contacts, recherches, paiements). Subtil et souvent oublié dans les audits.

Clickjacking

Attaque connexe : l'attaquant superpose de manière invisible le site cible dans une iframe et trompe la victime pour cliquer sur des boutons spécifiques (masqués). Protection : header X-Frame-Options ou frame-ancestors dans la CSP.

03 — DistinctionCSRF vs XSS

Deux attaques web classiques souvent confondues mais fondamentalement différentes.

Le XSS — exploite la confiance utilisateur envers le site

Le XSS injecte du code JavaScript dans une page web. Le serveur vulnérable diffuse du code qu'il n'aurait pas dû accepter. Quand la victime consulte la page, le code s'exécute dans son navigateur dans le contexte du site.

  • Faille côté serveur : restitution sans échappement.
  • Portée large : tout ce qu'un JS peut faire dans la page (vol de cookies, lecture de DOM, actions).
  • Pré-requis : vulnérabilité de sortie non échappée.
  • Protection : échappement contextuel, CSP, HttpOnly.

Le CSRF — exploite la confiance du site envers le navigateur

Le CSRF n'injecte rien sur le site cible. Il utilise le navigateur authentifié de la victime pour émettre des requêtes légitimes en apparence.

  • Pas de faille applicative classique : le site fonctionne normalement, c'est juste qu'il ne vérifie pas l'origine de la demande.
  • Portée limitée : seulement déclencher des actions prévues, avec les droits de la victime.
  • Pré-requis : absence de protection CSRF.
  • Protection : tokens CSRF, SameSite cookies, vérification Origin.

Tableau comparatif

  • Cible des dégâts : XSS = tout dans le navigateur ; CSRF = actions spécifiques.
  • Action requise de la victime : XSS = visiter la page vulnérable ; CSRF = être connecté ailleurs et visiter un site piégé.
  • Type de faille : XSS = injection ; CSRF = absence de vérification d'origine.
  • Visibilité côté serveur : XSS = stocké ou dans les logs ; CSRF = invisible, l'action semble légitime.

Relation dangereuse

Une XSS peut contourner toutes les protections CSRF : le JavaScript injecté par XSS s'exécute dans le contexte du site, peut lire le token CSRF de la page, puis émettre la requête avec le token valide. C'est pourquoi les bonnes pratiques exigent les deux protections indépendamment — l'une ne remplace pas l'autre.

Approches opposées

Les deux attaques illustrent deux philosophies de sécurité :

  • XSS : problème de données traitées comme code. Solution : séparer strictement code et données.
  • CSRF : problème de confiance trop large (cookies envoyés partout). Solution : exiger une preuve d'intention supplémentaire.

04 — ExemplesCas historiques marquants

ING Direct (2008)

Banque en ligne avec vulnérabilité CSRF permettant à un attaquant de forcer des transferts d'un compte victime vers un compte tiers. Découverte par des chercheurs académiques (William Zeller et Edward Felten de Princeton), patchée rapidement. Illustre la gravité du CSRF sur services financiers. L'étude de Princeton 2008 a été l'une des publications qui a fait prendre conscience de l'ampleur du problème — une demi-douzaine de sites majeurs vulnérables (YouTube, New York Times, Metafilter).

YouTube (2008)

Même étude Princeton : CSRF permettant d'ajouter des vidéos aux favoris, d'envoyer des messages, de changer des réglages de compte. YouTube a patché après divulgation responsable. Illustre que même les plateformes majeures manquaient de protection CSRF de base à l'époque.

The New York Times (2008)

Toujours dans la même étude : CSRF permettant à un attaquant de voler l'adresse email d'un abonné en exploitant la fonction « envoyer cet article à un ami ».

Netflix (2006-2008)

Plusieurs vulnérabilités CSRF permettant de modifier la liste de lecture, changer l'adresse de livraison DVD, et plus critique, changer l'adresse email et mot de passe du compte, conduisant à l'account takeover.

WordPress (multiples historiques)

WordPress et son écosystème de plugins ont connu de nombreuses CVE CSRF. Exemples notables : plusieurs plugins populaires avec CSRF permettant l'ajout d'un administrateur ou modification de code du site. Le core WordPress intègre maintenant wp_nonce en défense, mais les plugins restent une source régulière de découvertes.

GitHub (2012-2018, multiples)

Plusieurs CSRF patchées via leur programme bug bounty : changement d'adresse email, suppression de dépôts, modification de clés SSH. Chaque incident patché rapidement et gratifié. Montre que même les plateformes techniquement mûres découvrent régulièrement des cas subtils.

Routeurs domestiques (continu 2010+)

Catégorie très documentée : les interfaces d'admin de routeurs (TP-Link, D-Link, Netgear, Linksys) acceptaient des requêtes CSRF permettant :

  • Changement du DNS (pour rediriger tout le trafic).
  • Ouverture de ports (pour exposer des services internes).
  • Changement des credentials admin.
  • Exécution de commandes (via chaînage avec command injection).

Avec des credentials par défaut (admin/admin) et l'interface sur IP locale (192.168.1.1), une simple page web piégée pouvait compromettre le routeur. Des botnets ont exploité ces techniques à grande échelle.

CVE récentes (2022-2024)

  • GitLab : plusieurs CVE CSRF patchées, dont certaines permettant des changements de permissions.
  • Jenkins plugins : catégorie régulière dans les CVE, scripts admin exécutables via CSRF.
  • Solutions CRM et RH : CVE récurrentes dans des produits legacy.
  • WordPress plugins : toujours une source majeure de CVE CSRF.

Leçons récurrentes

  • Applications legacy : vrai angle mort — les applis sans framework moderne n'ont pas de protection CSRF par défaut.
  • Plugins et extensions : même quand le core est protégé, les extensions oublient régulièrement les tokens.
  • Infrastructures domestiques : routeurs, imprimantes, NAS — interfaces d'admin web souvent sans protection.
  • Impact indirect : un CSRF qui ajoute un admin permet ensuite de faire toutes les autres attaques.

05 — ProtectionBonnes pratiques modernes

Tokens CSRF synchronisés

Méthode historique la plus robuste. Le serveur génère un token aléatoire unique par session (ou par requête) et l'inclut dans chaque formulaire. Le client renvoie le token, le serveur vérifie qu'il correspond avant d'exécuter l'action.

<form action="/virement" method="POST">
  <input type="hidden" name="_csrf" value="a7b3c9d1e5f2..." />
  <input name="destinataire">
  <input name="montant">
</form>

Un site attaquant ne peut pas connaître le token (politique same-origin empêche de lire la page du site cible). Il ne peut donc pas construire une requête valide.

  • Intégré dans tous les frameworks modernes : Django CsrfViewMiddleware, Rails protect_from_forgery, Laravel @csrf, Spring Security CsrfFilter, ASP.NET Core AntiForgery.
  • Token doit être imprévisible (CSPRNG) et suffisamment long (min 128 bits).
  • Vérification côté serveur à chaque requête modifiant l'état.
  • Token invalidé au logout et à l'expiration de session.
Attribut SameSite des cookies

Protection au niveau navigateur généralisée depuis 2020. Limite l'envoi des cookies sur requêtes cross-site.

  • SameSite=Strict : cookie jamais envoyé en cross-site, même en suivant un lien externe. Plus sûr mais impacte UX (déconnexion lors de retour depuis un lien externe).
  • SameSite=Lax (défaut moderne) : cookie envoyé pour navigation top-level (liens, typage URL) mais pas pour iframes, images, POST cross-site. Bloque la majorité des CSRF tout en préservant l'UX.
  • SameSite=None : aucune restriction. Requiert Secure. À éviter sauf cas légitime (cross-site iframe, SSO).

Chrome a imposé SameSite=Lax par défaut en 2020, Firefox et Safari ont suivi. Cette seule mesure a éliminé la majorité des CSRF triviaux sur le web.

Vérification d'en-têtes Origin / Referer

Le navigateur ajoute l'en-tête Origin automatiquement sur les requêtes cross-origin non GET. Le serveur peut vérifier qu'il correspond au domaine attendu.

// Pseudo-code serveur
if (request.method in ['POST', 'PUT', 'DELETE']) {
  const origin = request.headers['origin'] || request.headers['referer'];
  if (!origin || !origin.startsWith('https://mon-site.com')) {
    throw new Error('CSRF detected');
  }
}
  • Complément aux tokens, pas substitut.
  • Attention aux cas limites : Origin absent sur certaines requêtes legacy, Referer filtré par politique stricte du navigateur.
  • Vérifier contre une liste blanche de domaines acceptables.
Double-submit cookies

Pour APIs stateless sans session serveur. Le serveur place un token aléatoire dans un cookie, le client doit le retransmettre dans un header custom (ex. X-CSRF-Token). Le serveur vérifie que les deux correspondent.

  • Un site attaquant ne peut pas lire le cookie (même-origine) ni en définir un valide.
  • Approche populaire pour les SPA (single-page apps).
  • Attention aux variantes faibles (cookie signé sans confrontation explicite).
Re-authentification pour actions critiques

Pour les actions vraiment sensibles (changement de mot de passe, transferts importants, suppression de compte), exiger une confirmation :

  • Re-saisie du mot de passe.
  • Code MFA additionnel.
  • Confirmation par email ou SMS.
  • Session élevée limitée dans le temps (ex. GitHub sudo mode, AWS console réauth).

Même si un CSRF passe, la re-authentification bloque l'exécution finale.

Bonnes pratiques méthodologiques
  • POST obligatoire pour toute action modifiant l'état (RFC 7231 : GET doit être safe).
  • APIs stateless avec JWT en header Authorization : non soumis aux cookies, donc non vulnérables au CSRF classique.
  • CORS correctement configuré : ne pas utiliser Access-Control-Allow-Origin: * avec credentials.
  • Content-Type strict : APIs JSON doivent exiger Content-Type: application/json (requête impossible via formulaire HTML simple, bloque des CSRF).
  • Tests automatisés : OWASP ZAP, Burp détectent l'absence de tokens CSRF.
  • Audit régulier : pentest couvrant explicitement CSRF.
Pièges classiques
  • « Notre API utilise POST donc elle est safe » : FAUX. Un formulaire HTML peut faire POST cross-site.
  • « SameSite=Lax bloque tout » : presque — mais GET top-level (liens) passent encore, attention aux actions via GET.
  • Vérifier uniquement Referer : contournable par politiques de confidentialité strictes qui l'omettent.
  • Token prévisible : utilisant l'ID session ou timestamp — craquable.
  • Token validé uniquement côté client : contournable trivialement.
  • Cross-site via sous-domaines : SameSite ne distingue pas toujours les sous-domaines — attention au partage de cookies avec des sous-domaines compromis.

06 — SameSiteLe web moderne

Le tournant 2020

L'évolution majeure : en février 2020, Chrome 80 a commencé à imposer SameSite=Lax par défaut pour tous les cookies sans attribut explicite. Firefox et Safari ont suivi. Conséquence directe : les CSRF les plus simples (formulaire auto-soumis cross-origin, image avec URL de modification) ne fonctionnent plus sans configuration spécifique côté serveur.

Impact mesurable

Les rapports de bug bounty post-2020 montrent une chute significative des paiements CSRF classiques. La vulnérabilité n'a pas disparu — elle s'est déplacée vers des cas plus subtils nécessitant des conditions particulières.

Les cas où SameSite ne protège pas

  • Actions via GET : SameSite=Lax permet toujours les requêtes top-level GET (cliquer un lien).
  • Attaquant dans le même site : XSS stored, sous-domaine compromis.
  • SameSite=None explicitement configuré : SSO, iframes légitimes cross-site.
  • Cookies partagés sur domaines parents : example.com vs api.example.com.
  • Applications sans cookies : JWT en localStorage — pas de CSRF classique, mais autres risques (XSS vole le token).

Implications pour les développeurs

  • Ne pas se reposer uniquement sur SameSite : garder les tokens CSRF comme défense en profondeur.
  • Attention aux changements d'UX : SameSite=Strict peut déconnecter l'utilisateur quand il revient depuis un lien externe — à utiliser judicieusement.
  • SSO et iframes : SameSite=None avec Secure est nécessaire, mais compensé par tokens et vérification Origin.
  • Audit de cookies : vérifier que les cookies de session ont bien un SameSite explicite.

Tendances futures

L'écosystème web continue d'évoluer :

  • Fetch Metadata : nouveaux en-têtes Sec-Fetch-Site, Sec-Fetch-Mode qui donnent plus de contexte au serveur pour décider si accepter la requête.
  • Cookies avec attribut Partitioned (CHIPS) : isolation des cookies tiers par site top-level.
  • CORS-RFC1918 (Private Network Access) : restriction des requêtes vers des réseaux privés (protège routeurs, printers).
  • Cookies first-party seulement : tendance structurelle à isoler les cookies par site.

Le CSRF classique est progressivement éliminé par l'évolution des standards — mais les applications doivent continuer à se défendre explicitement pour rester sûres quand les hypothèses implicites changent.

07 — FAQQuestions fréquentes

Pourquoi le CSRF n'est-il plus dans l'OWASP Top 10 depuis 2017 ?

Parce que les protections sont devenues largement intégrées par défaut dans les frameworks modernes. Django, Rails, Laravel, Spring Security, ASP.NET Core activent les tokens CSRF automatiquement. Les développeurs doivent explicitement désactiver la protection, ce qui est rare. L'OWASP considère que le risque résiduel est passé en-dessous du seuil du Top 10 — remplacé par « Insecure Design » et autres catégories plus préoccupantes aujourd'hui. Cela ne veut pas dire que le CSRF est un problème résolu : les applications legacy, plugins, produits embarqués restent vulnérables. OWASP maintient une Cheat Sheet CSRF Prevention actualisée qui est la référence technique.

Un site qui utilise JWT est-il protégé contre le CSRF ?

Ça dépend de comment le JWT est transmis. JWT en header Authorization (Bearer token) : immunisé au CSRF classique. Le navigateur n'ajoute pas automatiquement ce header sur requêtes cross-site, l'attaquant ne peut donc pas forger de requête valide. C'est la pratique recommandée pour les SPA et APIs. JWT stocké en cookie : vulnérable comme les sessions classiques. Les cookies sont envoyés automatiquement, il faut les protections CSRF habituelles. Le choix entre les deux dépend des contraintes XSS : un token en localStorage est volable par XSS, un cookie HttpOnly+Secure+SameSite ne l'est pas. Arbitrage classique entre les deux risques.

Un utilisateur peut-il être victime de CSRF s'il n'est pas connecté ?

Non pour le CSRF classique. Le CSRF exploite une authentification existante — si l'utilisateur n'est pas connecté, la requête forgée n'a pas de cookies de session à exploiter, le serveur la refuse comme non authentifiée. Exception : le Login CSRF forcerait la victime à se connecter avec les identifiants de l'attaquant. La victime utilise ensuite « son » compte sans savoir que c'est celui de l'attaquant, qui récupèrera tout ce qu'elle y stocke. Protection : protéger aussi le formulaire de login avec un token CSRF, ce qui est rarement fait car considéré comme non critique.

Peut-on contourner les tokens CSRF ?

Rarement quand ils sont correctement implémentés. Contournements théoriques et pratiques :

  • Token prévisible : mauvaise génération (séquentiel, basé sur timestamp).
  • Token non validé côté serveur : présent dans le formulaire mais jamais vérifié.
  • Token réutilisé trop longtemps : et ensuite divulgué par XSS ou fuite.
  • Token accepté via GET : log, referer, historique divulgue le token.
  • Vulnérabilité XSS sur le site : permet de lire le token dans le DOM.
  • Configuration CORS trop permissive : certains CORS mal configurés exposent les tokens.

Bien implémentés (framework moderne + bonne pratique), les tokens CSRF sont très difficiles à contourner sans faille complémentaire.

Combien vaut un CSRF en bug bounty ?

Paiements modestes comparés à d'autres vulnérabilités. Fourchettes typiques 2024-2026 :

  • CSRF sur action mineure (modification de préférence non critique) : 100-500 USD.
  • CSRF sur action sensible (changement email, ajout SSH key) : 500-2 000 USD.
  • CSRF permettant account takeover : 2 000-10 000 USD.
  • CSRF sur fonction financière (transfert, achat) : jusqu'à 20 000 USD sur les gros programmes.

Les paiements sont généralement plus bas que pour XSS ou SQLi car l'impact est plus limité (action précise vs contrôle total). Programmes HackerOne, Bugcrowd, YesWeHack reçoivent des rapports CSRF réguliers mais moins souvent critiques qu'autrefois.

Les API GraphQL sont-elles vulnérables au CSRF ?

Oui dans certaines configurations. GraphQL utilise généralement POST avec Content-Type: application/json, ce qui bloque les CSRF via formulaire HTML classique (navigateur envoie application/x-www-form-urlencoded). Mais vulnérabilités restent possibles si :

  • Le serveur accepte application/x-www-form-urlencoded.
  • Le serveur accepte GET pour les queries (pratique courante pour le caching).
  • CORS mal configuré autorise l'origine attaquante.
  • Authentification par cookies sans token CSRF supplémentaire.

Apollo Server, Hasura, PostGraphile offrent des options de protection CSRF mais ne les activent pas toujours par défaut. À vérifier explicitement.