CSRF et CORS : Sécuriser les requêtes navigateur
Vous avez construit une application web avec une API propre, mais vous remarquez des requêtes étranges dans vos logs—ou pire, un scanner de sécurité signale votre site pour des mauvaises configurations CSRF et CORS. Ces deux acronymes sont souvent confondus, mais ils résolvent des problèmes différents. Les mal comprendre peut exposer vos utilisateurs ou casser des requêtes cross-origin légitimes.
Dans cet article, nous clarifions ce que sont réellement CSRF et CORS, comment ils interagissent avec la sécurité du navigateur, et nous vous donnons des étapes concrètes pour sécuriser vos applications sans casser les fonctionnalités.
Qu'est-ce que le CSRF et pourquoi s'en soucier ?
Le Cross-Site Request Forgery (CSRF) est une attaque qui incite le navigateur d'un utilisateur à envoyer une requête vers un site où il est authentifié. Imaginez que vous êtes connecté à votre banque sur bank.com. Vous visitez ensuite un site malveillant contenant une balise image comme <img src="https://bank.com/transfer?to=attacker&amount=1000">. Votre navigateur inclut automatiquement vos cookies bancaires avec la requête, et si la banque n'a pas de protections CSRF, le virement est effectué.
Le point clé : le CSRF exploite la confiance qu'un site accorde au navigateur de l'utilisateur. L'attaquant n'a pas besoin de voler votre session ; il a juste besoin que votre navigateur fasse une requête en votre nom.
Comment fonctionnent les attaques CSRF
Pour qu'une attaque CSRF réussisse, trois conditions doivent être remplies :
- La victime doit être authentifiée (par exemple, avoir un cookie de session valide).
- L'attaquant doit connaître la structure de la requête (endpoint, paramètres).
- La requête ne doit pas inclure de paramètres imprévisibles que l'attaquant ne peut pas deviner.
Les cibles courantes sont les opérations modifiant l'état : changer d'email, transférer des fonds, publier du contenu ou modifier des permissions.
Qu'est-ce que le CORS et pourquoi existe-t-il ?
Le Cross-Origin Resource Sharing (CORS) est un mécanisme du navigateur qui autorise ou refuse aux pages web de faire des requêtes vers un domaine différent de celui qui a servi la page. C'est une extension de la Same-Origin Policy (SOP), qui restreint la façon dont un document ou un script chargé depuis une origine peut interagir avec des ressources d'une autre origine.
Sans CORS, un site malveillant pourrait utiliser JavaScript pour lire des données depuis l'API de votre banque si vous êtes connecté. CORS donne aux serveurs un moyen d'autoriser explicitement certaines requêtes cross-origin.
La Same-Origin Policy (SOP)
Deux URL ont la même origine si le protocole, l'hôte et le port sont identiques. Par exemple, https://example.com/app et https://example.com/api partagent la même origine, mais http://example.com (protocole différent) et https://api.example.com (hôte différent) ne la partagent pas.
La SOP empêche les scripts d'une origine de lire les réponses d'une autre origine. CORS assouplit cela en ajoutant des en-têtes HTTP qui indiquent au navigateur s'il faut autoriser la requête.
CSRF vs CORS : Différences clés
Il est crucial de comprendre que CSRF et CORS ne sont pas opposés ; ils traitent de préoccupations de sécurité différentes. Le CSRF vise à empêcher les requêtes non autorisées modifiant l'état, tandis que CORS contrôle quelles origines peuvent lire les réponses.
| Aspect | CSRF | CORS |
|---|---|---|
| Objectif principal | Empêcher les requêtes forgées | Contrôler les lectures cross-origin |
| Vecteur d'attaque | Un site malveillant déclenche des requêtes | Un site malveillant lit les réponses |
| Mécanisme de défense | Tokens, cookies SameSite | En-têtes HTTP (Access-Control-*) |
| Application par le navigateur | Aucune (le serveur doit valider) | Oui (le navigateur bloque les lectures) |
Comment se défendre contre le CSRF
Il existe plusieurs stratégies éprouvées pour atténuer le CSRF. Vous n'avez pas besoin de toutes les utiliser, mais superposer les défenses est judicieux.
1. Utilisez des tokens anti-CSRF
La défense la plus robuste consiste à inclure un token unique et imprévisible dans chaque requête modifiant l'état. Le serveur valide le token avant de traiter. Les tokens doivent être liés à la session de l'utilisateur et ne pas être exposés dans les URL (pour éviter les fuites via les en-têtes referrer).
// Exemple : Génération et validation d'un token CSRF dans Node.js/Express
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/process', csrfProtection, (req, res) => {
// Le token est automatiquement validé
res.send('OK');
});
2. Définissez des cookies SameSite
Les navigateurs modernes prennent en charge l'attribut SameSite pour les cookies. Le définir à Lax ou Strict empêche le navigateur d'envoyer des cookies lors de requêtes cross-site, ce qui bloque de nombreuses attaques CSRF. Lax autorise les cookies lors de navigations de haut niveau (par exemple, cliquer sur un lien), tandis que Strict bloque toutes les requêtes cross-site.
Set-Cookie: sessionId=abc123; SameSite=Lax; Secure; HttpOnly
3. Vérifiez les en-têtes Origin et Referer
Vérifiez l'en-tête Origin ou Referer sur les requêtes entrantes. S'ils ne correspondent pas à votre domaine attendu, rejetez la requête. C'est une couche supplémentaire simple mais efficace.
4. Utilisez des en-têtes personnalisés pour AJAX
Si votre API est consommée via JavaScript, exigez un en-tête personnalisé comme X-Requested-With. Les navigateurs appliquent le préflight CORS pour les en-têtes personnalisés, donc un simple POST de formulaire depuis un site malveillant ne l'inclura pas.
Configurer CORS correctement
Les mauvaises configurations CORS peuvent aussi entraîner des problèmes de sécurité. L'erreur la plus courante est de définir Access-Control-Allow-Origin: * tout en autorisant les credentials. Cette combinaison est interdite par les navigateurs, mais les développeurs tentent parfois de la contourner de manière non sécurisée.
Bonnes pratiques pour les en-têtes CORS
- Spécifiez des origines exactes au lieu de jokers lorsque des credentials sont impliqués.
- Limitez les méthodes autorisées à ce que votre API prend en charge (par exemple,
GET, POST). - Restreignez les en-têtes autorisés à ceux que votre application utilise réellement.
- Définissez
Access-Control-Max-Agepour mettre en cache les réponses préflight et réduire la surcharge. - Évitez de refléter aveuglément l'en-tête
Origin; validez-le par rapport à une liste blanche.
# Exemple : Configuration Nginx pour CORS
location /api/ {
if ($http_origin ~* (https://(app|admin)\.example\.com)) {
add_header 'Access-Control-Allow-Origin' $http_origin;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
}
if ($request_method = 'OPTIONS') {
return 204;
}
}
Rappelez-vous que CORS est appliqué par le navigateur, pas par le serveur. Ce n'est pas un substitut à l'authentification ou à l'autorisation ; c'est un moyen d'assouplir la same-origin policy en toute sécurité.
Mettre tout ensemble
Sécuriser les requêtes navigateur nécessite une approche en couches. Voici une liste de contrôle rapide :
- Utilisez des tokens anti-CSRF pour toutes les opérations modifiant l'état.
- Définissez des cookies SameSite à
LaxouStrict. - Validez les en-têtes Origin/Referer sur le serveur.
- Configurez CORS précisément : liste blanche d'origines, limitez les méthodes et évitez les jokers avec credentials.
- Testez régulièrement votre application avec des scanners de sécurité et des vérifications manuelles.
En comprenant les rôles distincts de CSRF et CORS, vous pouvez éviter les pièges courants et construire une application web plus sécurisée.
FAQ
CORS peut-il prévenir les attaques CSRF ?
Non, CORS ne prévient pas le CSRF. Les attaques CSRF ne reposent pas sur la lecture des réponses ; elles déclenchent simplement des requêtes. CORS contrôle quelles origines peuvent lire les réponses, mais il ne bloque pas l'envoi de la requête. Pour prévenir le CSRF, vous avez besoin de tokens, de cookies SameSite ou de validation d'origine.
Est-il sûr de définir Access-Control-Allow-Origin à '*' ?
Le définir à '*' est sûr uniquement si votre API n'utilise pas de credentials (cookies, authentification HTTP). Si des credentials sont impliqués, les navigateurs rejetteront la réponse. Pour les API authentifiées, spécifiez toujours des origines exactes.
Ai-je besoin d'une protection CSRF si j'utilise JWT dans les en-têtes Authorization ?
Si vous stockez des JWT dans des cookies, vous avez toujours besoin d'une protection CSRF car les cookies sont envoyés automatiquement. Si vous stockez des JWT en mémoire et les envoyez via l'en-tête Authorization, le CSRF n'est pas un problème car l'attaquant ne peut pas définir d'en-têtes personnalisés cross-origin. Cependant, vous devez vous protéger contre XSS pour garder le token en sécurité.
Prêt à tester les en-têtes CORS de votre API ? Utilisez notre Analyseur de logs Nginx pour inspecter les modèles de requêtes et repérer les tentatives cross-origin suspectes.