Les six en-têtes de sécurité à mettre sur chaque site
Quels en-têtes de réponse HTTP réduisent vraiment le risque, contre quoi chacun protège, les valeurs exactes à utiliser, et les erreurs qui rendent une CSP inutile.
Chaque réponse de votre serveur web commence par quelques lignes d’en-têtes. Les navigateurs les lisent avant la page, et certains changent ce que le navigateur autorise la page à faire : être affichée dans un cadre sur un autre site, laisser tourner un script injecté par un attaquant, imposer HTTPS à la visite suivante. Ils ne coûtent rien à ajouter ni à servir. La plupart des sites ne les mettent toujours pas, et un audit Perimetry d’un site de petite entreprise en trouve en général trois ou quatre qui manquent.
Ce guide couvre les six qui comptent, avec des valeurs à copier. Il ne couvre pas ceux qui ne servent plus à rien (X-XSS-Protection, Expect-CT, Public-Key-Pins) ; si vous les avez, retirez-les.
1. Strict-Transport-Security
Strict-Transport-Security: max-age=31536000; includeSubDomains
Une fois que le navigateur a vu cet en-tête sur votre site, il refuse pendant un an de s’y connecter en HTTP simple, même si l’utilisateur tape http:// ou clique sur un vieux lien. Cela ferme la fenêtre pendant laquelle une redirection de HTTP vers HTTPS peut être interceptée sur un réseau hostile. Il doit être envoyé en HTTPS pour compter, et max-age doit valoir au moins six mois (15 552 000 secondes) ; Perimetry signale les valeurs plus courtes.
N’ajoutez includeSubDomains que si tous les sous-domaines sont servis en HTTPS, ce qui devrait de toute façon être le cas. N’ajoutez preload que si vous inscrivez ensuite le domaine dans la liste de préchargement des navigateurs ; c’est une porte qui ne se rouvre pas facilement, lisez donc les conditions d’abord.
2. Content-Security-Policy
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests
La politique liste d’où le navigateur peut charger chaque type de ressource. Son but principal est de rendre le cross-site scripting inutile : un attaquant qui réussit à injecter <script> dans une page n’y gagne rien si la politique n’autorise que les scripts de votre propre domaine, et pas ceux écrits dans la page.
C’est aussi l’en-tête le plus souvent configuré d’une façon qui ne protège rien. Perimetry évalue la politique au lieu de seulement noter sa présence, et la juge faible quand :
script-srccontient'unsafe-inline'sans nonce ni empreinte. Cela autorise précisément les scripts injectés que l’en-tête doit bloquer.script-srccontient'unsafe-eval', ou un joker comme*ouhttps:.object-srcmanque : les plugins d’un autre âge et les intégrations<object>ne sont pas limités. Mettez-le à'none'.base-urimanque : une balise<base>injectée peut rediriger toutes les adresses relatives de la page.- L’en-tête est envoyé en mode « report-only » et rien ne l’applique.
Commencez par déployer la politique en Content-Security-Policy-Report-Only avec une adresse report-to pendant une semaine, corrigez les violations (en général des scripts écrits dans la page et des widgets tiers), puis passez en mode appliqué. Astro, Next.js et la plupart des frameworks savent produire des empreintes ou des nonces pour les scripts intégrés dont ils ont besoin.
3. X-Frame-Options et frame-ancestors
X-Frame-Options: DENY
Content-Security-Policy: ...; frame-ancestors 'none'
Les deux disent la même chose : personne ne peut afficher votre page dans un cadre. Sans eux, un attaquant peut charger votre site dans un cadre invisible sur sa propre page et amener un utilisateur connecté à cliquer sur des boutons qu’il ne voit pas (le « clickjacking »). frame-ancestors est la directive moderne et permet des exceptions (frame-ancestors 'self' https://partenaire.exemple) ; X-Frame-Options reste pour les très vieux navigateurs. Mettez les deux.
4. X-Content-Type-Options
X-Content-Type-Options: nosniff
Dit au navigateur de croire le Content-Type que vous envoyez et de ne jamais deviner. Sans lui, un fichier servi comme du texte peut être interprété comme un script s’il en a l’air, ce qui transforme une fonction d’envoi de fichiers en porte d’entrée pour des scripts. Il n’y a aucune raison de ne pas le mettre.
5. Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Règle quelle part de l’adresse courante est transmise aux autres sites quand un visiteur suit un lien ou charge une ressource. Les navigateurs récents utilisent déjà cette valeur par défaut, mais la fixer explicitement protège les visiteurs sur des navigateurs plus anciens et documente le choix. Si vos adresses contiennent quelque chose de privé (un jeton de réinitialisation, une recherche, un identifiant de compte), utilisez no-referrer ou same-origin.
6. Permissions-Policy
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()
Liste les fonctions du navigateur que vos pages (et les cadres qu’elles contiennent) peuvent utiliser. Pour un site qui n’a pas besoin de la caméra, le dire signifie qu’un script tiers compromis ne pourra pas la demander non plus. Listez les fonctions que vous utilisez avec (self).
Où les définir
Sur le serveur ou le proxy inverse, pas dans les gabarits de pages, pour que chaque réponse (y compris les erreurs, les redirections et les fichiers statiques) les porte :
- Nginx :
add_headerdans le bloc server, avecalwayspour qu’ils partent aussi sur les pages d’erreur. - Apache :
Header always setdans l’hôte virtuel ou le.htaccess. - Caddy : un bloc
header. - Cloudflare : Rules → Transform Rules → Modify Response Header, qui fonctionne même si l’origine ne les envoie pas.
- Node et Next.js : un middleware ; le paquet
helmetpose des valeurs raisonnables. - Astro :
security.cspdans la configuration produit une CSP à empreintes ; les autres en-têtes vont dans le serveur placé devant le site.
La CSP fait exception : comme elle dépend de ce que la page charge réellement, elle est souvent définie par l’application plutôt que par le proxy.
Vérifier le résultat
Chargez votre site, ouvrez les outils de développement du navigateur et regardez les en-têtes de réponse du document principal. Regardez ensuite la console : les violations de la CSP y sont notées avec la ressource bloquée et la directive qui l’a bloquée. Le contrôle web de Perimetry lit les mêmes en-têtes sur votre hôte principal et jusqu’à cinq autres sous-domaines exposés, évalue la CSP, et signale les cookies posés sans Secure ni HttpOnly et les politiques CORS qui acceptent n’importe quelle origine avec identifiants, les deux erreurs voisines.
À quoi ressemble le rapport
La Content-Security-Policy autorise les scripts intégrés — moyenne
https://www.votredomaine.frenvoie une politique, maisscript-srccontient'unsafe-inline'sans nonces ni empreintes : des scripts injectés s’exécuteraient. Remplacez'unsafe-inline'par des nonces propres à chaque réponse ou par les empreintes de vos scripts intégrés, et ajoutezobject-src 'none'; base-uri 'self'.
Un en-tête absent est un constat ; un en-tête présent mais faible en est un autre : un site qui met tout, mais mal, n’obtient pas le score d’un site correct.