Quels en-têtes sont utiles
- Strict-Transport-Security (HSTS) : les navigateurs ne chargent plus le site qu’en HTTPS.
- Content-Security-Policy (CSP) : définit d’où peuvent venir scripts, styles et cadres. La protection la plus efficace contre le XSS, mais aussi la plus exigeante.
- X-Content-Type-Options: nosniff : empêche les navigateurs de deviner le type de fichier.
- Referrer-Policy : limite ce qui est transmis lors d’un clic vers un autre site.
- Permissions-Policy : désactive caméra, micro, localisation etc. si tu n’en as pas besoin.
- frame-ancestors (dans la CSP) ou X-Frame-Options : protection contre le clickjacking.
X-XSS-Protection n’est plus nécessaire. Les navigateurs modernes l’ignorent, et dans les anciens il pouvait même nuire.
nginx
# /etc/nginx/snippets/security-headers.conf add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; add_header Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always; # dans le bloc server : include snippets/security-headers.conf; server_tokens off;
nginx a deux pièges :
- Sans
always, les en-têtes manquent sur les pages d’erreur et les redirections (p. ex. 404, 301). - Pas d’héritage : dès qu’un bloc
locationa son propreadd_header, les en-têtes du blocservern’y valent plus. Inclure donc aussi le fichier avecincludedans ces blocslocation.
Apache
# sudo a2enmod headers
<VirtualHost *:443>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
Header always unset X-Powered-By
</VirtualHost>
# global, p. ex. dans security.conf
ServerTokens Prod
ServerSignature Off
Sur un hébergement mutualisé sans accès à la configuration du serveur, les mêmes lignes Header fonctionnent en général dans le .htaccess à la racine. La version de PHP dans l’en-tête X-Powered-By se désactive avec expose_php = Off dans php.ini.
Mettre en place la CSP sans casser le site
Une CSP trop stricte bloque tes propres scripts, les vidéos intégrées ou les outils d’analyse. Procède donc par étapes :
- D’abord en
Content-Security-Policy-Report-Only. Le navigateur ne bloque rien mais signale les violations dans la console. - Parcourir la console sur les pages importantes et ajouter les sources nécessaires, p. ex.
script-src 'self' https://cdn.example.net. - Déplacer les scripts en ligne dans des fichiers ou leur donner un nonce.
'unsafe-inline'dansscript-srcannule en grande partie la protection contre le XSS. - Seulement ensuite passer à
Content-Security-Policy.
Prudence avec HSTS
HSTS ne se retire pas facilement : les navigateurs le retiennent pour la durée indiquée. Commence avec max-age=300, vérifie que tous les sous-domaines gèrent vraiment HTTPS, puis passe à deux ans. includeSubDomains concerne aussi des noms internes comme intranet.example.com s’ils sont sous le même domaine.
Vérifier
curl -sI https://example.com curl -sI https://example.com/nexiste-pas # aussi en 404 ?
La vérification des en-têtes de sécurité évalue tous les en-têtes, repère les erreurs typiques comme 'unsafe-inline' et génère les lignes adaptées à ton serveur.
FAQ
X-Frame-Options suffit-il ou faut-il frame-ancestors ?
frame-ancestors dans la CSP est la méthode moderne et permet plusieurs sources. Pour de très vieux navigateurs, ajouter X-Frame-Options: SAMEORIGIN ne nuit pas.
Pourquoi vois-je les en-têtes en double ?
En général, l’application (p. ex. PHP ou un CMS) et le serveur web les définissent tous les deux. Deux CSP sont appliquées toutes les deux, la plus stricte l’emporte. Mieux vaut les définir à un seul endroit.
Les API ont-elles besoin d’en-têtes de sécurité ?
Oui, au moins HSTS, nosniff et une CSP stricte comme default-src 'none'; frame-ancestors 'none'. Ils ne coûtent rien et empêchent l’abus des réponses dans le navigateur.
Un CDN définit-il les en-têtes pour moi ?
Seulement si tu le configures. Beaucoup de CDN transmettent simplement les en-têtes du serveur d’origine.