Cross-site request forgery (CSRF)¶
La falsification de requête inter-sites (Cross-Site Request Forgery, CSRF) consiste à faire exécuter, par le navigateur d'une victime authentifiée, une requête qu'elle n'a pas initiée. L'attaque exploite le fait que le navigateur joint automatiquement les cookies de session à toute requête vers un site — y compris une requête déclenchée depuis une page malveillante. Si ce site valide la requête sur la seule base du cookie présent, il l'accepte comme si elle émanait légitimement de la victime.
Concrètement, l'attaquant héberge une page qui émet une requête vers le site cible. Il suffit que la victime ait une session active sur ce site et visite la page piégée pour que la requête parte et soit validée. Une attaque CSRF réussie permet de déclencher une action sensible — changer une adresse e-mail, un mot de passe — au nom de la victime.
Les conditions d'une CSRF¶
Trois conditions doivent être réunies : une action intéressante à provoquer, une gestion de session fondée uniquement sur les cookies (sans autre jeton imprévisible), et aucun paramètre imprévisible dans la requête. Les défenses tournent précisément autour de ces points : jeton anti-CSRF, attribut SameSite sur les cookies, vérification de l'en-tête Referer.
Forme de base¶
Sans protection, une simple page auto-soumise suffit. Le formulaire reproduit la requête sensible et se soumet seul au chargement :
<form action="https://site-vulnerable.example/my-account/change-email" method="POST">
<input type="hidden" name="email" value="attaquant@exemple.net" />
</form>
<script>document.forms[0].submit();</script>
Lorsqu'un jeton anti-CSRF est présent mais mal vérifié, plusieurs failles le rendent inopérant : le jeton n'est validé que sur certaines méthodes, ou il n'est pas lié à la session de l'utilisateur, ou il est dupliqué dans un cookie qu'on peut influencer. Les sections qui suivent détaillent les contournements selon le mécanisme de défense rencontré.
Contourner les défenses SameSite¶
L'attribut SameSite d'un cookie contrôle s'il est envoyé lors d'une requête inter-sites. C'est aujourd'hui la principale protection, mais elle laisse plusieurs angles.
SameSite=Lax (le défaut moderne). Chrome applique Lax par défaut, ce qui bloque l'envoi des cookies sur les requêtes POST inter-sites. On peut souvent contourner cela en forçant l'application à traiter une requête GET comme un POST, via un paramètre de surcharge de méthode :
<script>
document.location = "https://site-vulnerable.example/my-account/change-email?email=attaquant@exemple.net&_method=POST";
</script>
La requête part en GET (donc avec le cookie), mais l'application l'interprète en POST. Une autre voie consiste à détourner une fonctionnalité du site lui-même, comme une redirection après publication, pour atteindre l'endpoint sensible.
La fenêtre des 120 secondes. Quand SameSite n'est pas défini explicitement, Chrome applique Lax — mais seulement après un délai de 120 secondes suivant la création du cookie. Pendant cette fenêtre, les requêtes POST inter-sites passent encore. On peut en profiter en forçant la victime à générer un cookie frais juste avant l'attaque, par exemple en déclenchant une reconnexion via un flux de connexion sociale (SSO) :
<form method="POST" action="https://site-vulnerable.example/my-account/change-email">
<input type="hidden" name="email" value="attaquant@exemple.net">
</form>
<p>Cliquez n'importe où sur la page</p>
<script>
window.onclick = () => {
window.open('https://site-vulnerable.example/social-login');
setTimeout(() => document.forms[0].submit(), 5000);
}
</script>
SameSite=Strict. Ce réglage retire le cookie de toute requête inter-sites. Un contournement possible passe par un gadget de redirection côté client construit dynamiquement à partir d'une entrée contrôlable (voir la section sur les redirections ouvertes basées sur le DOM), qui transforme la requête en requête same-site.
Jeton lié à un cookie hors session¶
Quand le jeton anti-CSRF est validé par comparaison avec un cookie distinct (et non avec la session), on peut parfois injecter son propre cookie. Si une fonctionnalité du site réfléchit une entrée dans un en-tête de réponse, une injection d'en-tête permet d'y glisser un Set-Cookie. Encodée dans une URL, elle se déclenche via un élément image dont le gestionnaire d'erreur soumet ensuite le formulaire :
<img src="https://site-vulnerable.example/?search=test%0d%0aSet-Cookie:%20csrfKey=VALEUR_ATTAQUANT%3b%20SameSite=None" onerror="document.forms[0].submit()" />
L'attaquant fixe ainsi à la fois le cookie de jeton et la valeur correspondante dans le formulaire, qui concordent — la vérification passe.
Contourner les défenses fondées sur le Referer¶
Certains sites vérifient l'en-tête Referer plutôt que d'utiliser SameSite. Cette défense est plus faible, car le Referer peut être retiré ou manipulé.
Si le retrait du Referer suffit à contourner la vérification, une simple méta-balise l'élimine :
Si la validation est laxiste — l'en-tête doit seulement commencer par ou contenir le bon domaine — on intègre le domaine attendu dans son propre Referer. La méthode history.pushState permet d'ajouter le domaine attendu au chemin de l'URL courante :
Beaucoup de navigateurs tronquant la chaîne de requête du Referer, on force son envoi complet via une politique explicite :
Aide-mémoire¶
| Défense rencontrée | Contournement |
|---|---|
| Aucune | Formulaire HTML auto-soumis |
| Jeton non lié à la session | Injection de cookie via en-tête réfléchi |
SameSite=Lax (défaut) |
Surcharge de méthode _method=POST, redirection interne |
SameSite non défini |
Fenêtre de 120 s après reconnexion forcée |
SameSite=Strict |
Gadget de redirection côté client (same-site) |
Referer (retrait suffisant) |
Méta-balise no-referrer |
Referer (validation laxiste) |
pushState + Referrer-Policy: unsafe-url |
Le générateur de preuve de concept CSRF intégré à Burp Suite (clic droit sur une requête → Generate CSRF PoC) produit automatiquement le formulaire correspondant à une requête interceptée.