Protection CSRF et prévention de la falsification de formulaires

Comprenez les attaques CSRF et comment les jetons empêchent un attaquant de détourner vos formulaires. Pourquoi chaque formulaire doit être protégé.

Brouillon

Imaginez que quelqu'un pousse un visiteur à cliquer sur un lien pendant qu'il est connecté à son compte bancaire. Ce lien mène à un formulaire caché qui, à l'insu du visiteur, envoie à la banque une demande de virement. La banque voit une demande légitime venant d'un utilisateur authentifié et l'exécute. L'attaquant a déplacé de l'argent depuis le compte de la victime sans jamais connaître son mot de passe.

C'est ce qu'on appelle une attaque CSRF (Cross-Site Request Forgery) : l'attaquant pousse une victime à envoyer, sans le savoir, un formulaire ou une requête vers un autre site où elle est déjà connectée.

Ce que vous allez apprendre : ce que sont les attaques CSRF et comment elles fonctionnent, pourquoi elles restent dangereuses même quand d'autres mesures de sécurité sont en place, comment les jetons CSRF les empêchent et comment protéger vos formulaires.

Qu'est-ce que le CSRF ?

CSRF (qui se prononce « sea-surf ») signifie Cross-Site Request Forgery, c'est-à-dire falsification de requête intersite. Dans cette attaque, l'attaquant exploite un fait simple : quand vous êtes connecté à un site, votre navigateur fait confiance à votre session et l'inclut automatiquement dans chaque requête vers ce site, même si la requête provient d'un autre site.

L'attaque consiste à pousser un visiteur connecté à envoyer, sans le savoir, un formulaire vers un site où il a un compte. L'attaquant ne voit pas le mot de passe de la victime. Il n'en a pas besoin. Il lui suffit que la victime soit déjà connectée, puis de l'amener à faire une requête (comme envoyer un formulaire caché) qui produit l'effet voulu.

Le CSRF diffère des autres attaques, car il n'exige ni vol d'identifiants ni cassage de chiffrement. Il exploite la confiance de la victime envers le site. La victime est déjà authentifiée, donc le site fait confiance aux requêtes qui semblent venir d'elle.

Comment fonctionnent les attaques CSRF

Une attaque CSRF se déroule en trois étapes.

Étape 1 : la victime est connectée à votre site

Quelqu'un visite votre site et se connecte à son compte. Son navigateur détient alors un cookie de session actif qui prouve son authentification. Cette session reste active tant qu'elle continue d'utiliser le site.

Étape 2 : l'attaquant l'amène sur une page malveillante

Toujours connectée à votre site, la victime visite une page contrôlée par l'attaquant (un lien sur les réseaux sociaux, une publicité trompeuse ou un site d'apparence légitime). Sur cette page se trouve un code caché qui envoie un formulaire vers votre site.

Étape 3 : le formulaire s'envoie tout seul avec la session de la victime

Le formulaire caché est envoyé à votre site. Comme la victime est déjà connectée, son navigateur ajoute automatiquement son cookie de session à la requête. Du point de vue de votre formulaire, c'est une requête légitime d'un utilisateur authentifié. Il la traite comme si la victime l'avait envoyée volontairement.

L'attaquant a maintenant fait quelque chose sur votre site avec le compte de la victime, sans qu'elle le sache. Il a pu changer son mot de passe, faire un virement, modifier son profil ou envoyer des données.

Pourquoi l'attaque fonctionne malgré d'autres mesures de sécurité

Les attaques CSRF contournent plusieurs protections courantes :

HTTPS n'arrête pas le CSRF. Les données sont chiffrées pendant le transport, mais l'attaquant n'a pas besoin de les intercepter. Il envoie simplement la requête depuis le navigateur de la victime, auquel ce navigateur fait déjà confiance.

La protection par mot de passe n'arrête pas le CSRF. L'attaquant n'a jamais besoin du mot de passe de la victime. Il exploite le fait qu'elle est déjà connectée.

Un système de connexion solide n'arrête pas le CSRF. Même si l'authentification est parfaite, dès que la victime est connectée, l'attaque fonctionne.

C'est pourquoi la protection CSRF forme une couche à part. Les autres mesures de sécurité ne l'assurent pas. Il faut concevoir vos formulaires pour résister spécifiquement à ces attaques.

Les jetons CSRF : comment ils bloquent l'attaque

La solution est un jeton CSRF. C'est une chaîne unique et imprévisible que votre serveur génère pour chaque formulaire. Voici comment cela marche :

Votre serveur crée un jeton unique pour chaque visiteur

Quand quelqu'un charge une page contenant un formulaire, votre serveur génère un jeton aléatoire et l'associe à la session de cet utilisateur. Ce jeton est différent à chaque fois et propre à cet utilisateur.

Le jeton est intégré au formulaire

Le jeton est inclus dans le formulaire HTML sous forme de champ caché. Quand le visiteur envoie le formulaire, le jeton part avec.

Votre serveur vérifie le jeton avant de traiter l'envoi

À la réception, votre serveur vérifie que le jeton reçu correspond à celui généré pour la session de cet utilisateur. Si oui, le formulaire est traité. Si non (ou s'il n'y a pas de jeton), il est rejeté.

Le formulaire caché de l'attaquant ne peut pas contenir de jeton valide, car les jetons sont imprévisibles et propres à chaque session. Un attaquant sur un autre domaine ne peut ni voir ni deviner le jeton. Son attaque échoue donc. Le formulaire caché est envoyé, mais votre serveur le rejette parce que le jeton ne correspond pas.

À quoi ressemble un jeton CSRF en pratique

En HTML, un formulaire protégé contre le CSRF ressemble à ceci :

<form method="POST" action="/submit-form"> <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"> <input type="email" name="email" placeholder="Your email"> <button type="submit">Submit</button> </form>

Le champ `csrf_token` est caché. Le visiteur ne le voit pas, mais il est envoyé avec les données du formulaire. Votre serveur le vérifie avant de traiter l'e-mail ou toute autre donnée.

La protection CSRF selon le type de formulaire

Formulaires HTML classiques

Les formulaires HTML standard (ceux qui envoient les données à votre serveur en POST) ont besoin de jetons CSRF. Cela inclut les formulaires de contact, de connexion, de réinitialisation de mot de passe et tout formulaire qui modifie des données sur votre serveur.

Formulaires AJAX et JavaScript

Les formulaires envoyés en JavaScript vers une API ont eux aussi besoin d'une protection CSRF. Le jeton peut être intégré au formulaire, stocké dans un cookie ou récupéré dans une balise meta avant l'envoi de la requête.

Requêtes d'API sans état

Si votre API utilise une authentification par jeton (comme JWT), la protection CSRF fonctionne autrement. Le navigateur ne peut pas joindre automatiquement un jeton JWT comme il joint un cookie de session, donc le CSRF classique est une menace moindre. La bonne pratique reste pourtant d'ajouter un jeton CSRF pour plus de sécurité.

D'autres protections qui complètent les jetons CSRF

Les jetons CSRF sont la défense principale, mais ils fonctionnent mieux avec d'autres bonnes pratiques de sécurité.

Cookies SameSite

Quand vous définissez un cookie de session, vous pouvez lui ajouter un attribut `SameSite` qui indique au navigateur de ne pas l'envoyer quand la requête vient d'un autre domaine. Le formulaire caché de l'attaquant ne peut alors plus du tout utiliser la session de la victime.

Vérification de l'en-tête Referer

Votre serveur peut vérifier l'en-tête Referer pour savoir d'où vient la requête. Si un envoi prétend venir de votre domaine alors que le Referer indique un autre domaine, c'est probablement une attaque. (Cependant, les en-têtes Referer peuvent être falsifiés : ce n'est donc pas une défense complète.)

Cookie à double envoi

Dans cette approche, le jeton CSRF est stocké à la fois dans un cookie et dans un champ du formulaire. Votre serveur vérifie qu'ils correspondent avant de traiter la requête. C'est moins courant que les jetons classiques, mais cela convient bien aux applications sans état.

Comment mettre en place la protection CSRF

Les détails dépendent de votre technologie, mais le schéma est toujours le même :

  1. Générer un jeton unique par session. Quand un utilisateur démarre une session ou charge une page de formulaire, votre serveur génère un nouveau jeton.
  2. Stocker le jeton côté serveur. Enregistrez-le en l'associant à la session de cet utilisateur.
  3. Inclure le jeton dans le formulaire. Ajoutez-le comme champ caché dans le HTML ou comme balise meta que JavaScript peut lire.
  4. Valider à l'envoi. Avant de traiter les données, vérifiez que le jeton reçu correspond à celui enregistré pour cette session.
  5. Régénérer après une action sensible. Quand un utilisateur change son mot de passe ou fait une action critique, générez un nouveau jeton.

La plupart des frameworks modernes gèrent automatiquement la génération et la validation des jetons CSRF. Si vous utilisez un framework, la protection est généralement activée par défaut. Veillez simplement à ne pas la désactiver par accident.

Les erreurs courantes qui laissent les formulaires vulnérables

Désactiver la protection CSRF par commodité. Certains développeurs coupent les contrôles CSRF pour faciliter les tests d'API ou simplifier leur code. Ne le faites pas. Cela crée une vraie faille.

Utiliser un jeton statique pour tous les utilisateurs. Le jeton doit être propre à la session de chaque utilisateur. Un jeton identique pour tout le monde (ou identique pour tous les utilisateurs, tous les jours) ne protège pas du CSRF.

Ne pas régénérer les jetons. Si vous gardez le même jeton pendant des semaines, un attaquant a plus de temps pour l'exploiter. Régénérez les jetons régulièrement, et toujours après une opération sensible.

Ne compter que sur les cookies SameSite. SameSite est utile mais insuffisant. Faites des jetons CSRF votre défense principale et de SameSite un renfort.

Oublier le jeton sur certains formulaires. Si vous protégez certains formulaires et pas d'autres, les attaquants passeront par ceux qui ne le sont pas. Tout formulaire qui modifie des données doit être protégé.

Ce que fait WEMASY pour la protection CSRF

Les formulaires WEMASY incluent automatiquement une protection par jeton CSRF sur chaque formulaire que vous créez. Vous n'avez rien à configurer ni à y penser. Quand un visiteur envoie un formulaire, WEMASY valide le jeton avant d'enregistrer la réponse. Cette protection est intégrée et activée par défaut.

Découvrez les options de sécurité des formulaires sur la page des tarifs.

Questions fréquentes

Un attaquant peut-il deviner un jeton CSRF ?
En théorie, non. Les jetons CSRF sont aléatoires au sens cryptographique et changent souvent. Un attaquant qui tenterait de deviner un jeton devrait essayer des milliards de possibilités. En pratique, les jetons CSRF sont si imprévisibles que deviner n'est pas une attaque réaliste. La force du jeton vient de son caractère aléatoire et unique, pas du fait de le garder secret.
Que se passe-t-il si un visiteur envoie un formulaire avec un jeton invalide ?
L'envoi est rejeté. Votre serveur ne traite pas les données du formulaire et n'enregistre pas la réponse. Le visiteur voit généralement un message d'erreur (comme « Session expirée » ou « Requête invalide ») et doit réessayer. Du point de vue de l'attaquant, le formulaire caché ne fonctionne tout simplement pas.
Ai-je besoin d'une protection CSRF si mon formulaire n'exige pas de connexion ?
Oui. Les attaques CSRF peuvent viser des formulaires sans authentification. Un attaquant peut s'en servir pour pousser un visiteur à envoyer des données non voulues à n'importe quel formulaire, que le visiteur soit connecté ou non. Tout formulaire qui traite des envois a besoin d'une protection CSRF.
Quelle différence entre CSRF et XSS ?
Le Cross-Site Scripting (XSS) consiste à injecter du code malveillant dans votre site, qui s'exécute dans le navigateur des visiteurs. Le CSRF consiste à pousser le navigateur d'un visiteur à envoyer un formulaire vers un autre site. Ce sont deux attaques différentes, avec des défenses différentes. Les jetons CSRF protègent contre le CSRF ; la validation et le nettoyage des saisies protègent contre le XSS.
Et les attaques visant les applications mobiles ? Les jetons CSRF fonctionnent-ils ?
Les applications mobiles sont moins exposées au CSRF classique, car elles n'ajoutent pas automatiquement les cookies comme le font les navigateurs. Elles devraient pourtant utiliser une authentification par jeton ou par certificat. Si une application mobile utilise des cookies ou des jetons envoyés automatiquement avec les requêtes, elle devrait aussi valider des jetons CSRF comme couche de protection supplémentaire.

Mettez-le en pratique
sur votre propre site.

Commencez gratuitement avec WEMASY et créez votre site en quelques minutes.