Sécuriser les en-têtes HTTP avec nginx / protection contre les attaques web courantes

Un serveur web bien configuré ne se contente pas de servir des pages, il communique aussi avec le navigateur du visiteur via des en-têtes HTTP. Ces en-têtes peuvent soit révéler des informations sensibles sur l’infrastructure, soit au contraire instruire le navigateur sur la manière de traiter le contenu de façon sécurisée. Configurer les bons en-têtes de sécurité est une mesure simple, rapide à mettre en place et efficace contre plusieurs catégories d’attaques web courantes.

Pourquoi les en-têtes HTTP sont importants

Par défaut, nginx expose des informations inutiles, sa version exacte apparaît dans chaque réponse HTTP. Un attaquant qui connaît ta version de nginx peut cibler des vulnérabilités connues spécifiques à cette version.

D’autre part, sans directives explicites, le navigateur du visiteur ne sait pas comment se protéger contre certaines attaques , il acceptera de charger ton site dans une iframe sur n’importe quel domaine, devinera le type des fichiers uploadés, ou transmettra l’URL complète de tes pages aux sites tiers.

Les en-têtes de sécurité règlent ces problèmes en quelques lignes de configuration.

Évaluer l’état actuel

Avant de configurer quoi que ce soit, vérifions les en-têtes actuellement retournés par notre serveur :

curl -I https://monsite.fr

Sur un serveur non configuré tu verras typiquement :

HTTP/1.1 200 OK
Server: nginx/1.24.0

Deux problèmes visibles : la version nginx est exposée, et aucun en-tête de sécurité n’est présent.

Tu peux également tester ton site sur securityheaders.com qui donne une note de A à F et liste les en-têtes manquants.

Configuration

Plutôt que de dupliquer les en-têtes dans chaque virtual host, on crée un fichier de configuration global chargé automatiquement par nginx :

sudo nano /etc/nginx/conf.d/security-headers.conf
# Masquer la version nginx
server_tokens off;

# Headers de sécurité
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Teste la configuration et recharge nginx :

sudo nginx -t && sudo systemctl reload nginx

Explication de chaque directive

server_tokens off

Cache la version exacte de nginx dans les réponses HTTP. Sans cette directive, nginx affiche Server: nginx/1.24.0 — une information précieuse pour un attaquant qui cherche des vulnérabilités connues sur une version spécifique. Avec server_tokens off, la réponse affiche simplement Server: nginx.

Protège contre : fingerprinting du serveur, ciblage de vulnérabilités par version.


X-Frame-Options "SAMEORIGIN"

Contrôle si ton site peut être chargé dans une <iframe> sur un autre domaine. La valeur SAMEORIGIN signifie que seules les pages de ton propre domaine peuvent intégrer ton site en iframe.

Protège contre : le clickjacking — une technique où un attaquant superpose ton site invisible sur un autre pour piéger l’utilisateur à cliquer sur des éléments à son insu, par exemple valider une action bancaire ou changer un mot de passe.


X-Content-Type-Options "nosniff"

Interdit au navigateur de deviner le type MIME d’un fichier si le serveur l’a déjà déclaré. Sans ce header, un navigateur pourrait interpréter un fichier texte uploadé par un utilisateur comme du JavaScript exécutable.

Protège contre : le MIME sniffing, une technique d’attaque où un fichier malveillant uploadé (image, document) est réinterprété par le navigateur comme du code exécutable.


X-XSS-Protection "1; mode=block"

Active le filtre XSS intégré dans les navigateurs anciens. Lorsqu’une tentative de Cross-Site Scripting est détectée, le navigateur bloque complètement le chargement de la page plutôt que d’essayer de la nettoyer.

Protège contre : les attaques XSS (Cross-Site Scripting) sur les navigateurs anciens. Les navigateurs modernes ont leur propre protection intégrée, mais ce header assure la compatibilité avec les anciens clients.


Referrer-Policy "strict-origin-when-cross-origin"

Contrôle quelles informations sont transmises dans l’en-tête Referer lors d’une navigation. Avec cette valeur :

  • Navigation sur ton propre domaine → l’URL complète est transmise
  • Navigation vers un domaine externe → seul le nom de domaine est transmis
  • Navigation de HTTPS vers HTTP → rien n’est transmis

Protège contre : la fuite d’URLs internes sensibles (pages d’administration, tokens dans les URLs) vers des sites tiers via l’en-tête Referer.


Permissions-Policy "geolocation=(), microphone=(), camera=()"

Désactive explicitement l’accès à la géolocalisation, au microphone et à la caméra pour ton site. Même si une faille XSS permettait d’injecter du code malveillant dans tes pages, ce code ne pourrait pas demander l’accès à ces ressources sensibles.

Protège contre : l’accès abusif aux ressources matérielles du visiteur via du code JavaScript injecté.


Strict-Transport-Security "max-age=31536000; includeSubDomains"

C’est le HSTS (HTTP Strict Transport Security). Il dit au navigateur de ne jamais accéder à ton site en HTTP, même si l’utilisateur tape http:// ou clique sur un lien non sécurisé. La connexion est automatiquement forcée en HTTPS côté navigateur.

  • max-age=31536000 : cette règle est mémorisée pendant 1 an (365 jours)
  • includeSubDomains : s’applique également à tous les sous-domaines

Protège contre : les attaques man-in-the-middle qui interceptent la connexion HTTP initiale avant la redirection HTTPS, et les attaques de downgrade qui forcent une connexion non chiffrée.

⚠️ Attention!!! n’active HSTS qu’après avoir vérifié que HTTPS fonctionne correctement sur tous tes sous-domaines. Une fois le header envoyé, le navigateur refusera toute connexion HTTP pendant max-age secondes.

Vérification

Après rechargement de nginx, vérifions que les en-têtes sont bien présents :

curl -I https://monsite.fr

Tu dois voir dans la réponse :

HTTP/1.1 200 OK
Server: nginx
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Strict-Transport-Security: max-age=31536000; includeSubDomains

Note que Server: nginx n’affiche plus la version, server_tokens off est bien actif.

Tu peux également tester sur securityheaders.com pour obtenir une note et vérifier qu’aucun en-tête important ne manque.

Conclusion

La configuration des en-têtes de sécurité HTTP est l’une des mesures les plus simples à mettre en place, quelques lignes de configuration dans nginx suffisent pour renforcer significativement la posture de sécurité d’un serveur web. Ces en-têtes sont aujourd’hui considérés comme des standards — leur absence est systématiquement signalée comme une vulnérabilité dans les audits de sécurité web.

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *