Headers de sécurité : HSTS, CSP, X-Frame-Options et autres
· 7 min de lecture
Le backend est une forteresse, mais l'autre moitie de la defense est dans le navigateur. HSTS, CSP et autres en-tetes bloquent XSS, clickjacking et MITM.
Pourquoi ils comptent
Une application peut être parfaitement sécurisée côté backend et rester vulnérable aux attaques côté navigateur : cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Les headers de sécurité déplacent la défense dans le navigateur lui-même.
Strict-Transport-Security (HSTS)
Force HTTPS pour toutes les visites futures. Après la première visite en HTTPS, le navigateur mémorise le domaine et réécrit de lui-même tout lien http:// en https://, même si l'utilisateur clique sur un mauvais lien.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
max-age=63072000= valide 2 ansincludeSubDomains= la règle s'applique aussi à tous les sous-domaines ; elle force HTTPS partout, donc un sous-domaine ne tournant qu'en HTTP, par ex.staging.example.com, devient inaccessible dans le navigateurpreload= permet l'inclusion dans la liste HSTS preload intégrée à Chrome / Firefox / Safari
Attention :
Retirer un HSTS avec preload de la liste prend 6+ mois. N'ajoutez pas preload avant d'avoir vérifié que HTTPS fonctionne de manière stable sur tous les sous-domaines.
Content-Security-Policy (CSP)
Le header le plus puissant, mais aussi le plus difficile à configurer. Il whiteliste d'où le navigateur peut charger scripts, styles, images et iframes. Sans CSP, un attaquant capable d'injecter une balise <script> peut exécuter n'importe quel JS ; avec CSP, seulement du code provenant de sources approuvées.
Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'
Directives courantes :
default-src 'self'= par défaut, n'autoriser que les ressources de mon propre domainescript-src= sources JS (pour les scripts inline, indiquez un hash ou une nonce)style-src= sources CSSimg-src= imagesconnect-src= AJAX, WebSocket, EventSourceframe-ancestors 'none'= personne ne peut embarquer la page dans une iframe (mieux que X-Frame-Options)report-uri /csp-report= le navigateur envoie un JSON à chaque violation (vous l'attrapez dans le backend et la loggez)- Note :
report-uriest aujourd'hui deprecated - les navigateurs qui supportentreport-tol'ignorent. La méthode moderne est la directivereport-toplus un en-têteReporting-Endpointsséparé ; gardezreport-uriuniquement comme fallback pour Firefox, qui ne supporte pas encorereport-to.
X-Frame-Options
Alternative plus ancienne à frame-ancestors. Empêche le clickjacking, où l'attaquant intègre votre page comme iframe et la recouvre de boutons invisibles.
X-Frame-Options: DENY
Valeurs : DENY (personne), SAMEORIGIN (uniquement mon domaine), ALLOW-FROM uri (deprecated).
X-Content-Type-Options
X-Content-Type-Options: nosniff
Désactive le MIME sniffing, de sorte que le navigateur respecte le Content-Type renvoyé par le serveur. Sans cela, un attaquant peut uploader un fichier au mauvais type (par ex. une image qui est en réalité du HTML avec script) et le navigateur peut l'exécuter comme une page web.
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Contrôle la quantité d'informations sur la page précédente que le navigateur envoie dans le header Referer au clic. La valeur par défaut dans les navigateurs modernes est déjà strict-origin-when-cross-origin, mais définir le header explicitement garantit un comportement cohérent.
Permissions-Policy
Désactive les API dont vous n'avez pas besoin, comme la caméra, le microphone, le GPS et la géolocalisation. Un attaquant exploitant une XSS ne peut pas demander ces API.
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Configuration pratique en nginx
server {
listen 443 ssl http2;
server_name example.com;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
# nous avons volontairement omis preload ici - ne l'ajoute que lorsque tu es sûr à 100% (voir le piège preload plus haut)
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# CSP est étendu - définissez-le selon votre application
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}
La clé est always - sans cela, nginx omet les headers sur les réponses d'erreur (4xx, 5xx).
Audit de l'état actuel
Le plus simple est un outil en ligne. Notre header check vous montre quels headers manquent et lesquels sont incorrects. Pour un audit approfondi, securityheaders.com donne en plus une note A-F.
Conclusion
Les headers de sécurité comptent parmi les meilleurs investissements en sécurité au regard du rapport effort/gain : typiquement une demi-heure de configuration dans un reverse proxy contre toute une catégorie d'attaques côté navigateur. Un audit une fois par semestre dans le cadre de la maintenance régulière est un minimum raisonnable.
Audit gratuit des security headers
Sans inscription, résultat en trois secondes.
Essayez ePulz.io gratuitement - 7 jours sans carte de crédit.
Créer un compte