Retour au blog

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.

Headers de sécurité : HSTS, CSP, X-Frame-Options et autres

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 ans
  • includeSubDomains = 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 navigateur
  • preload = 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 domaine
  • script-src = sources JS (pour les scripts inline, indiquez un hash ou une nonce)
  • style-src = sources CSS
  • img-src = images
  • connect-src = AJAX, WebSocket, EventSource
  • frame-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-uri est aujourd'hui deprecated - les navigateurs qui supportent report-to l'ignorent. La méthode moderne est la directive report-to plus un en-tête Reporting-Endpoints séparé ; gardez report-uri uniquement comme fallback pour Firefox, qui ne supporte pas encore report-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.

Tester le site →

Partager: Lien copié

Essayez ePulz.io gratuitement - 7 jours sans carte de crédit.

Créer un compte