Les en-tetes de securite HTTP qui comptent : CSP, HSTS, X-Content-Type-Options, X-Frame-Options et Referrer-Policy expliques

Pourquoi les en-têtes de réponse HTTP sont importants pour la sécurité

Chaque réponse HTTP comporte des en-têtes — des lignes de métadonnées envoyées avant le corps qui contrôlent la façon dont le navigateur traite le contenu. La plupart des en-têtes sont banals (Content-Type, Cache-Control), mais un ensemble spécifique d'en-têtes de sécurité indique au navigateur d'appliquer des restrictions qui bloquent des catégories entières d'attaques. Ce ne sont pas des mesures de renforcement théoriques ; ce sont des défenses pratiques contre des classes d'attaques qui apparaissent régulièrement dans le Top 10 de l'OWASP et les bases de données CVE. Les configurer ne coûte rien en termes de performance — ils ajoutent environ 200–400 octets à chaque réponse — et des outils comme securityheaders.com attribuent une note à n'importe quelle URL publique pour que vous puissiez immédiatement voir quels en-têtes manquent.

L'idée clé est que les en-têtes de sécurité sont appliqués par le navigateur, pas par le serveur. Le serveur annonce une politique ; le navigateur la fait respecter. Cela signifie qu'une mauvaise configuration des en-têtes sur un site à fort trafic affecte simultanément le navigateur de chaque visiteur. À l'inverse, l'ajout des bons en-têtes corrige des années de risques accumulés en un seul déploiement. Les cinq en-têtes couverts ici — CSP, HSTS, X-Content-Type-Options, X-Frame-Options et Referrer-Policy — ciblent chacun un comportement différent du navigateur que les attaquants peuvent exploiter.

Content-Security-Policy : le pare-feu contre le XSS

Le Cross-Site Scripting (XSS) est la vulnérabilité web la plus courante dans le Top 10 de l'OWASP. Un attaquant capable d'injecter une balise <script> dans votre HTML peut voler des cookies de session, rediriger des utilisateurs ou exfiltrer des données de formulaire. Content-Security-Policy (CSP) est un en-tête basé sur liste blanche qui indique au navigateur quelles sources sont fiables pour les scripts, les styles, les images, les polices et autres types de ressources. La directive Content-Security-Policy: default-src 'self' n'autorise que les ressources provenant de la même origine, bloquant tous les scripts externes et les blocs <script> en ligne. Une directive script-src remplace la valeur par défaut spécifiquement pour JavaScript.

Le plus grand piège de CSP est le mot-clé unsafe-inline. Ajouter script-src 'unsafe-inline' réactive les scripts en ligne et rend totalement inefficace la protection XSS de CSP, pourtant c'est la solution la plus recherchée quand un site se casse après avoir activé CSP. La bonne alternative est les nonces : chaque chargement de page génère une valeur aléatoire cryptographiquement, incluse comme script-src 'nonce-r4nd0m' dans l'en-tête et comme nonce="r4nd0m" sur chaque balise <script> légitime. Un script injecté sans le nonce correspondant est bloqué même s'il apparaît en ligne. Pour les équipes pas encore prêtes pour une politique stricte, Content-Security-Policy-Report-Only envoie des rapports de violation à un endpoint de collecte sans rien bloquer — une façon sûre de mesurer l'impact d'une politique avant de l'appliquer.

HTTP Strict Transport Security : prévenir les attaques de dégradation HTTPS

Le SSL stripping est une attaque de dégradation démontrée publiquement à Black Hat 2009. Un attaquant actif sur le chemin intercepte la requête HTTP initiale de l'utilisateur (avant toute redirection vers HTTPS) et la proxifie en HTTP simple vers l'origine, tout en servant la connexion chiffrée à l'utilisateur. L'utilisateur voit un cadenas dans certains navigateurs, mais la connexion entre l'attaquant et le serveur est la connexion non chiffrée — les identifiants et les cookies de session sont visibles en clair. HTTP Strict Transport Security (HSTS) ferme cette fenêtre en indiquant aux navigateurs de refuser entièrement les connexions HTTP pour un domaine, pendant une période définie par la directive max-age en secondes.

Un en-tête HSTS fort typique est Strict-Transport-Security: max-age=31536000; includeSubDomains; preload. Le max-age de 31536000 secondes représente un an — le minimum requis pour l'inclusion dans la liste de préchargement HSTS. includeSubDomains étend la politique à chaque sous-domaine. preload signale l'intention d'être inclus dans la liste de préchargement livrée avec le navigateur sur hstspreload.org ; une fois sur cette liste, les navigateurs refuseront les connexions HTTP même avant d'avoir jamais visité le site et reçu l'en-tête. La contrainte critique : HSTS doit être délivré via une réponse HTTPS valide. Un en-tête envoyé via HTTP est ignoré. Testez avant de déployer includeSubDomains — si un sous-domaine manque d'un certificat TLS valide, les utilisateurs seront bloqués pendant toute la durée max-age.

X-Content-Type-Options et X-Frame-Options : deux améliorations de sécurité à valeur unique

Le MIME sniffing est un comportement hérité où certains navigateurs inspectent les premiers octets d'une réponse pour deviner son type de contenu, ignorant l'en-tête Content-Type. Internet Explorer était le sniffer de MIME le plus agressif ; il exécuterait un .jpg comme HTML si les premiers octets ressemblaient à du balisage. Un attaquant capable de télécharger du contenu sur votre site (une image, un fichier journal) peut créer une charge utile qui s'exécute comme un script lorsque le navigateur la reniffle. X-Content-Type-Options: nosniff indique à tous les navigateurs modernes de faire confiance au Content-Type déclaré et d'ignorer entièrement le sniffing. Il n'a qu'une seule valeur valide — nosniff — et il n'y a aucune raison de ne pas le définir sur chaque réponse.

Le clickjacking intègre votre site dans un <iframe> sur une page contrôlée par l'attaquant, puis superpose des boutons transparents pour que les utilisateurs cliquent involontairement sur des éléments UI de votre site. X-Frame-Options: DENY empêche votre page d'être encadrée par quiconque ; X-Frame-Options: SAMEORIGIN n'autorise l'encadrement que par des pages du même origine. La variante ALLOW-FROM uri est obsolète et non supportée dans les navigateurs actuels. L'équivalent moderne est la directive CSP frame-ancestors (frame-ancestors 'none' correspond à DENY, frame-ancestors 'self' correspond à SAMEORIGIN), qui prend en charge en outre plusieurs origines autorisées. Comme tous les navigateurs ne vérifient pas frame-ancestors dans tous les contextes, définir à la fois X-Frame-Options et une directive CSP frame-ancestors offre une défense en profondeur.

Referrer-Policy : contrôler les fuites d'informations via l'en-tête Referer

L'en-tête HTTP Referer (orthographié avec une seule 'r' en raison d'une faute de frappe historique dans le RFC) envoie l'URL complète de la page depuis laquelle l'utilisateur a navigué à chaque ressource externe que cette page charge — images, scripts, feuilles de style et destinations des clics sur les liens. Si un utilisateur connecté visite /account/reset?token=eyJ... et que cette page charge un script d'analyse tiers, la requête du script porte l'URL complète incluant le token de réinitialisation dans l'en-tête Referer. La fuite de tokens via le referrer est une classe de vulnérabilité bien documentée ; GitHub a corrigé une exposition de tokens basée sur le referrer aussi récemment qu'en 2020.

L'en-tête Referrer-Policy remplace l'ancien mécanisme Meta referrer et les contournements de suppression de l'en-tête Referer. La politique strict-origin-when-cross-origin est la valeur par défaut recommandée : elle envoie l'URL complète pour les requêtes de même origine (utile pour l'analytique interne), mais seulement l'origine nue (https://example.com) pour les requêtes d'origine croisée, et rien lors de la navigation de HTTPS vers HTTP. no-referrer n'envoie rien du tout, maximisant la confidentialité mais cassant tout analytique dépendant du referrer. unsafe-url envoie toujours l'URL complète incluant le chemin et la chaîne de requête — la valeur par défaut du navigateur avant 2020 et la source de la plupart des fuites historiques de referrer. Chrome, Firefox et Safari ont tous adopté strict-origin-when-cross-origin comme valeur par défaut en 2020–2021 lorsqu'aucun en-tête de politique n'est présent, mais le définir explicitement garantit un comportement cohérent sur toutes les versions de navigateur.

Une base d'en-têtes de sécurité pratique pour n'importe quel site

Pour un site statique ou une application web simple, quatre en-têtes couvrent les vecteurs d'attaque les plus courants avec une complexité de configuration minimale : X-Content-Type-Options: nosniff (toujours, une ligne) ; X-Frame-Options: SAMEORIGIN (sauf si votre site doit être intégré légitimement) ; Referrer-Policy: strict-origin-when-cross-origin ; et Strict-Transport-Security: max-age=31536000; includeSubDomains (une fois que vous avez confirmé que chaque sous-domaine est HTTPS). CSP nécessite plus de planification — commencez par Content-Security-Policy-Report-Only et un endpoint de rapport, collectez des violations pendant quelques jours, puis rédigez une politique n'autorisant que ce que vous utilisez réellement.

L'emplacement de configuration des en-têtes dépend de votre stack : Nginx utilise des directives add_header dans le bloc serveur ; Apache utilise Header always set dans httpd.conf ou .htaccess ; Vercel, Netlify et Cloudflare Pages ont chacun un fichier de configuration des en-têtes ou un paramètre de tableau de bord. La plupart des CDN permettent l'injection d'en-têtes en périphérie, ce qui est préférable aux en-têtes au niveau de l'application car le CDN les délivre même pour les réponses mises en cache. L'outil HTTP Headers Checker de TeaFun récupère n'importe quelle URL publique et affiche quels en-têtes de sécurité sont présents, leurs valeurs et une explication de référence rapide de ce que fait chacun — utilisez-le pour auditer un site avant et après le déploiement de changements d'en-têtes.