CSRF (CWE-352, OWASP A01:2021) : tromper un utilisateur authentifié pour exécuter des actions non souhaitées via l'envoi automatique des cookies.
TL;DR
SameSite — 96,48 % manquent de la principale défense modernetext/plain contourne le preflight CORS sans en-têtes personnalisésLe Cross-Site Request Forgery (CSRF, CWE-352) est une vulnérabilité web qui force les utilisateurs authentifiés à exécuter des actions modifiant l'état qu'ils n'ont pas initiées. Contrairement au XSS, l'attaquant n'a pas besoin d'accéder au token de session de la victime — le mécanisme d'envoi automatique de cookies du navigateur fait le travail. Quand la victime visite la page de l'attaquant, le navigateur inclut silencieusement tous les cookies de session valides pour le domaine cible sur toute requête embarquée, et le serveur cible traite cette requête comme si elle provenait de l'utilisateur.
Le CSRF a été retiré de l'OWASP Top 10 en 2021 en supposant que les cookies SameSite, désormais défaut sous Chrome 80+ et la plupart des navigateurs modernes, élimineraient la plupart des vecteurs. En pratique, la menace n'a pas disparu : CVE-2024-20252 (Cisco Expressway, CVSS 9.6, février 2024) et CVE-2024-23897 (Jenkins CLI, CVSS 9.8, catalogue CISA KEV, janvier 2024) reposent tous deux sur le CSRF comme vecteur primaire ou facilitateur. Un audit 2024 a révélé que seulement 3,52 % des sites web avaient un attribut SameSite défini, ce qui signifie que la grande majorité des applications en production fonctionnent encore sans cette défense.
Trois conditions doivent être simultanément vraies pour qu'une attaque CSRF réussisse : (1) une action privilégiée modifiant l'état existe — changement de mot de passe, virement de fonds, création de compte, opération administrative ; (2) l'application authentifie l'utilisateur exclusivement via des cookies, sans vérification complémentaire comme un en-tête personnalisé ou un token CSRF ; et (3) tous les paramètres de requête nécessaires à l'exécution de l'action sont prévisibles ou connus de l'attaquant. Quand ces trois conditions sont réunies, l'attaquant peut construire une page qui déclenche l'action avec une seule visite de la victime.
La Same-Origin Policy du navigateur empêche JavaScript de lire les réponses cross-origin, mais elle n'empêche pas les requêtes cross-origin d'être envoyées. Une page sur evil.com peut amener le navigateur à effectuer une requête GET ou POST vers bank.com, et le navigateur joint dûment les cookies de bank.com. Le serveur reçoit une requête syntaxiquement valide et authentifiée sans indication qu'elle provient d'une page hostile.
L'attaque se déroule en cinq étapes :
banque.com — cookie de session défini.evil.com (page contrôlée par l'attaquant), via phishing ou une publicité embarquée.banque.com.banque.com reçoit la requête, valide le cookie de session, ne trouve aucune vérification de token CSRF, et exécute l'action.La règle RFC 9110 §9.2 sur les méthodes sûres stipule que les requêtes GET NE DOIVENT PAS modifier l'état du serveur. Les exploits CSRF basés sur GET ciblent les applications qui violent cette règle — un anti-pattern courant dans le code hérité, les panneaux d'administration avec des liens d'action rapide, et les endpoints de déconnexion.
| Variante | Mécanisme | Contournement principal | Impact |
|---|---|---|---|
| GET classique | <img>, <a>, window.location déclenchent un GET authentifié | Les GET d'état ignorent SameSite=Lax sur la navigation de premier niveau | Action de compte, suppression de données |
| POST (formulaire) | Formulaire caché auto-soumis, upload multipart | Omission de token : le serveur valide seulement si le champ est présent | Changement de mot de passe, d'email, suppression de compte |
| JSON CSRF | enctype="text/plain" crée un corps JSON, sans preflight CORS | Le serveur analyse le corps quel que soit le Content-Type | Changement d'état API, mutations GraphQL |
| Contournement SameSite | 5 chemins de contournement : nav GET, fenêtre Lax+POST 2 min, redirection ouverte, XSS sous-domaine, Origin null | Fenêtre de grâce Chrome de 120 secondes pour les cookies sans SameSite explicite | CSRF complet malgré la défense SameSite |
| Login CSRF | Formulaire pré-auth auto-connecte la victime dans le compte de l'attaquant | Aucune session n'existe, donc aucun token émis | Collecte de données, chaîne Self-XSS, injection de code OAuth |
Comprendre quand les cookies sont envoyés en intersite est fondamental pour comprendre la surface d'attaque :
| Cookie SameSite | Formulaire POST intersite | Navigation GET premier niveau | Sous-ressource <img> | Notes |
|---|---|---|---|---|
Strict | Bloqué | Bloqué | Bloqué | Le plus sûr. Peut casser les flux OAuth/SSO retour arrière |
Lax (défaut Chrome 80+) | Bloqué | Envoyé | Bloqué | Les GET d'état restent exposés |
None; Secure | Envoyé | Envoyé | Envoyé | Requis pour les widgets de paiement, les intégrations intersites |
| Absent (Chrome 80+, nouveau cookie) | Envoyé dans la fenêtre de 120 s | Envoyé | Bloqué | La fenêtre de grâce Chrome Lax+POST est exploitable |
SameSite=Lax est le défaut de Chrome pour les cookies sans attribut explicite, mais il ne protège pas les endpoints GET modifiant l'état. L'envoi de cookies lors de la navigation de premier niveau est conçu ainsi — cela signifie que toute redirection window.location ou clic sur <a href> vers un endpoint GET sensible réussit avec les identifiants de la victime.
CVE-2024-20252 / CVE-2024-20254 — Cisco Expressway Series (CVSS 9.6, Critique) : Des protections CSRF insuffisantes sur l'API web Cisco Expressway permettaient à un attaquant distant non authentifié de tromper un administrateur authentifié pour qu'il suive un lien forgé. L'attaque déclenchait des modifications de configuration arbitraires, la création de comptes avec des privilèges élevés et des conditions de DoS — le tout au niveau de privilège de l'administrateur. CVE-2024-20254 était exploitable dans la configuration par défaut. Publié en février 2024, patch requis, aucune solution de contournement.
CVE-2024-23897 — Jenkins CLI (CVSS 9.8, CISA KEV, Critique) : L'analyseur CLI args4j de Jenkins remplaçait les arguments @<chemin_fichier> par le contenu du fichier. Des attaquants lisaient /var/jenkins_home/secrets/master.key de manière non authentifiée, extrayaient le secret de token CSRF, forgeaient des tokens CSRF valides et exécutaient des actions CLI privilégiées sans aucune interaction utilisateur au-delà de l'exploit initial. Ajouté au catalogue CISA KEV en août 2024 avec une échéance de patch obligatoire au 9 septembre 2024.
CVE-2024-4994 — GitLab CE/EE GraphQL (CVSS 8.1, Élevé) : CSRF sur l'endpoint /api/graphql permettait à des attaquants non authentifiés d'exécuter des mutations GraphQL arbitraires au nom de victimes authentifiées. GraphQL acceptait des mutations via des types de contenu qui ne déclenchaient pas de preflight CORS, contournant la protection supposée. HackerOne #1122408 (prime de 3 370 $) a documenté le vecteur de mutation via requête GET sur le même endpoint.
HackerOne #1497169 — GitHub Enterprise Management Console (10 000 $) : La prime CSRF la plus élevée connue sur HackerOne. L'attaque contournait la protection CSRF dans la console de gestion du serveur GitHub Enterprise, permettant des actions administratives arbitraires sur l'infrastructure enterprise.
delete, update, transfer, create dans les chemins).csrf_token, authenticity_token, _token, __RequestVerificationToken ou XSRF-TOKEN.Content-Type: text/plain et observer si le serveur analyse encore et exécute le corps.Set-Cookie. Relever la valeur SameSite (ou son absence). Tester les endpoints GET modifiant l'état directement via navigation de premier niveau.?_method=POST ou l'en-tête X-HTTP-Method-Override: POST aux requêtes GET ciblant des endpoints POST. Les frameworks comme Symfony, Rails et Laravel acceptent ces overrides.Le générateur de PoC CSRF de Burp Suite Pro identifie la surface d'attaque ; la règle 20012 d'OWASP ZAP signale les tokens manquants. XSRFProbe effectue une analyse approfondie des tokens incluant l'omission, le token vide, le token aléatoire et la réutilisation entre utilisateurs. Les scanners automatisés ratent les vulnérabilités de token non lié à la session (réutilisation de token entre utilisateurs) et les chaînes de contournement SameSite nécessitant une exploitation en plusieurs étapes.
BreachVex détecte le CSRF via plusieurs techniques complémentaires : analyse de token de formulaire avec sonde d'API JSON, sonde POST cross-origin avec comparaison de référence et logique de saut sensible aux segments, et sonde GET différentielle qui détecte la divergence de réponse entre requête authentifiée et non authentifiée.
Générer un token aléatoire cryptographiquement lié à la session par session utilisateur. L'intégrer dans chaque formulaire modifiant l'état. Le valider côté serveur à chaque requête modifiant l'état, rejetant les requêtes qui l'omettent ou présentent un token invalide.
# FastAPI — génération et validation du token CSRF
import secrets
from fastapi import Request, HTTPException, Form
def generate_csrf_token() -> str:
return secrets.token_urlsafe(32) # 256 bits d'entropie
def validate_csrf_token(request: Request, csrf_token: str = Form(...)):
session_token = request.session.get("csrf_token")
if not session_token or not secrets.compare_digest(session_token, csrf_token):
raise HTTPException(status_code=403, detail="Token CSRF invalide ou manquant")Utiliser secrets.compare_digest (comparaison en temps constant) pour prévenir les attaques oracle de timing. Les tokens doivent être uniques par session, pas par requête — les tokens par requête cassent les applications multi-onglets.
Définir SameSite=Strict sur les cookies de session pour bloquer toutes les requêtes intersites, y compris la navigation de premier niveau. Utiliser le préfixe de cookie __Host- pour prévenir les attaques d'injection depuis les sous-domaines.
Set-Cookie: __Host-SID=<token>; Path=/; Secure; HttpOnly; SameSite=Strict__Host- exige Secure, Path=/ et aucun attribut Domain — empêchant les sous-domaines d'injecter un cookie correspondant qui pourrait contourner les schémas de double cookie soumis.
Implémenter une politique d'isolation de ressources utilisant les en-têtes Sec-Fetch-Site, que les navigateurs modernes joignent à toutes les requêtes (couverture 98%+ mondiale en 2025) :
# FastAPI — politique d'isolation de ressources
METHODES_SURES = {"GET", "HEAD", "OPTIONS"}
SITES_AUTORISES = {"same-origin", "same-site", "none"}
def resource_isolation_policy(request: Request):
site = request.headers.get("Sec-Fetch-Site", "")
mode = request.headers.get("Sec-Fetch-Mode", "")
dest = request.headers.get("Sec-Fetch-Dest", "")
if request.method in METHODES_SURES or site in SITES_AUTORISES:
return
if mode == "navigate" and dest not in ("object", "embed"):
return # Autoriser la navigation navigateur de premier niveau
raise HTTPException(status_code=403, detail="Requête intersite rejetée")Ne jamais se reposer sur une seule défense CSRF. SameSite seul échoue pour les endpoints GET et la fenêtre de 2 minutes. Les tokens CSRF seuls échouent si le token n'est pas lié à la session (réutilisation entre utilisateurs). Implémenter SameSite=Strict + tokens CSRF + Fetch Metadata pour une défense en profondeur.
Les tokens CSRF peuvent être révélés via BREACH (Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext) lorsque le serveur compresse des réponses contenant à la fois le token et une entrée contrôlée par l'attaquant dans le même corps. L'oracle de compression Huffman révèle le token caractère par caractère via des mesures de longueur de texte chiffré. Atténuation : utiliser le masquage de token par requête (nonce XOR, tel qu'implémenté par la librairie csrf-csrf), ou désactiver la compression HTTP sur les réponses transportant des secrets.
XMLHttpRequest ; le Login CSRF s'enchaîne avec le XSS stocké pour la prise de contrôle de compte.Le Cross-Site Request Forgery (CSRF, CWE-352) force les utilisateurs authentifiés à soumettre à leur insu des requêtes modifiant l'état d'une application de confiance. Le navigateur joint automatiquement les cookies de session à chaque requête vers un domaine — la page de l'attaquant exploite ce mécanisme pour forger des actions privilégiées sans jamais accéder à la session de la victime.
Trois conditions doivent être simultanément réunies : (1) une action exploitable modifiant l'état existe sur la cible, (2) l'authentification de session repose exclusivement sur les cookies sans mécanisme complémentaire comme des en-têtes personnalisés, et (3) tous les paramètres de requête nécessaires à l'exécution de l'action sont prévisibles par l'attaquant.
Oui. CVE-2024-20252 (Cisco Expressway, CVSS 9.6) et CVE-2024-23897 (Jenkins, CVSS 9.8, CISA KEV) exploitent tous deux le CSRF comme vecteur primaire ou facilitateur. Seulement 3,52 % des sites web implémentent l'attribut SameSite, ce qui signifie que la grande majorité des applications manque encore de la principale défense CSRF moderne.
Non. SameSite=Lax bloque les formulaires POST intersites mais envoie les cookies lors des navigations GET de premier niveau. Les endpoints GET modifiant l'état restent totalement exploitables. L'astuce de remplacement de méthode (?_method=POST) exploite les endpoints POST protégés par Lax via GET. La fenêtre de grâce Chrome de 2 minutes Lax+POST autorise les POST intersites pour les cookies nouvellement émis sans attribut SameSite explicite.
Le XSS injecte et exécute du JavaScript dans le contexte du navigateur de la victime, permettant le vol de cookies et la manipulation arbitraire du DOM. Le CSRF exploite l'envoi automatique des cookies par le navigateur pour forger des requêtes authentifiées — aucune exécution de code n'est requise. Le XSS peut escalader le CSRF en volant des tokens CSRF ; le CSRF peut escalader le XSS via le Login CSRF qui fait exécuter des payloads stockés dans le compte de l'attaquant.
Non. HTTPS chiffre la couche transport mais ne prévient pas le CSRF. La page de l'attaquant sur evil.com provoque l'envoi par le navigateur de la victime d'une requête HTTPS authentifiée vers target.com. TLS protège le canal, pas l'origine de la requête.
Le serveur génère un token aléatoire cryptographiquement lié à la session (minimum 128 bits, CSPRNG) et l'intègre dans chaque formulaire modifiant l'état. Le serveur valide le token à chaque requête modifiant l'état, rejetant les requêtes qui l'omettent ou le falsifient. C'est la principale défense CSRF pour les applications à rendu serveur.
Non. Les APIs JSON sont vulnérables via le contournement Content-Type text/plain : un formulaire HTML avec enctype='text/plain' envoie un POST avec un corps en forme JSON sans déclencher de preflight CORS. CVE-2024-4994 (GitLab GraphQL, CVSS 8.1) et CVE-2022-41919 (Fastify) démontrent ce vecteur contre de vraies APIs en production.
Le Login CSRF force la victime à s'authentifier en tant que compte de l'attaquant. Comme l'endpoint de connexion n'a pas de session préexistante à protéger, la plupart des applications ignorent la protection CSRF là. L'attaquant récupère ensuite toutes les données soumises par la victime — détails de carte de crédit, informations personnelles — qui atterrissent dans le contexte du compte de l'attaquant.
Burp Suite Pro inclut un générateur de PoC CSRF (clic droit sur la requête → Engagement tools → Generate CSRF PoC). La règle de scan actif 20012 d'OWASP ZAP détecte les tokens anti-CSRF manquants. XSRFProbe CLI teste l'omission de token, les tokens vides, les tokens aléatoires et la réutilisation de token entre utilisateurs. BreachVex automatise la détection CSRF sur toutes les cinq classes de variantes, y compris JSON et le contournement SameSite.