Security Headers
Les en-têtes HTTP de sécurité représentent une couche de défense fondamentale et souvent sous-utilisée pour les applications web modernes, agissant comme des directives qui demandent aux navigateurs d'activer des mécanismes de protection natifs contre un large éventail de vecteurs d'attaque courants. Ces en-têtes de réponse HTTP fonctionnent comme une politique de sécurité déclarative, établissant des règles sur la façon dont le navigateur doit traiter et afficher le contenu de la page, contrôler l'exécution des scripts, gérer les cookies et interagir avec les ressources tierces. Lorsqu'ils sont correctement configurés, des en-têtes comme Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), X-Frame-Options et X-Content-Type-Options créent des barrières importantes contre les attaques de Cross-Site Scripting (XSS), de clickjacking, de MIME sniffing, de downgrade de protocole et d'injection de code malveillant. La mise en œuvre correcte de ces en-têtes représente l'une des façons les plus efficaces de durcir les applications web, car elle ne nécessite aucune modification du code de l'application et offre une protection immédiate contre des classes entières de vulnérabilités. Des études montrent que la grande majorité des sites n'implémente toujours pas correctement ces en-têtes, laissant leurs utilisateurs exposés à des attaques qui pourraient être atténuées avec des configurations relativement simples sur le serveur web. Cette négligence est particulièrement critique si l'on considère que les outils automatisés de scan de sécurité évaluent la présence et la configuration adéquate de ces en-têtes comme des indicateurs primaires de la posture de sécurité d'une application.
Content-Security-Policy (CSP)
CSP prévient le XSS en définissant une whitelist de sources de confiance pour les scripts, styles, images et autres ressources.
# CSP stricte (recommandé)
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-';
style-src 'self' 'nonce-';
img-src 'self' https: data:;
font-src 'self';
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
# CSP avec report-only (mode test)
Content-Security-Policy-Report-Only:
default-src 'self';
report-uri /csp-violation-report
Directives CSP critiques
- default-src : Fallback pour les autres directives
- script-src : Whitelist pour l'exécution de JavaScript
- style-src : Sources CSS autorisées
- frame-ancestors : Prévient le clickjacking
- upgrade-insecure-requests : Force le HTTPS
Strict-Transport-Security (HSTS)
HSTS force les navigateurs à toujours utiliser HTTPS, prévenant les downgrade attacks et le SSL stripping.
# HSTS avec preload et sous-domaines
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Étapes pour le HSTS preload :
1. Configurer l'en-tête HSTS avec preload
2. Soumettre le domaine sur hstspreload.org
3. Le domaine sera inclus dans les preload lists des navigateurs
X-Frame-Options
Prévient le clickjacking en contrôlant si la page peut être affichée dans un frame/iframe.
# Refuser tout framing (le plus sûr)
X-Frame-Options: DENY
# Autoriser uniquement la même origine
X-Frame-Options: SAMEORIGIN
# Autoriser un domaine spécifique (obsolète - utiliser CSP frame-ancestors)
X-Frame-Options: ALLOW-FROM https://trusted.com
X-Content-Type-Options
Prévient les attaques de MIME sniffing en forçant le navigateur à respecter le Content-Type déclaré.
# Désactiver le MIME sniffing
X-Content-Type-Options: nosniff
Referrer-Policy
Contrôle la quantité de referrer information envoyée dans les requests.
# Politique recommandée
Referrer-Policy: strict-origin-when-cross-origin
# Options :
# - no-referrer : Ne jamais envoyer le referrer
# - no-referrer-when-downgrade : Pas de referrer sur HTTPS→HTTP
# - same-origin : Envoyer uniquement à la même origine
# - strict-origin : Envoyer uniquement l'origine (sans le path)
Permissions-Policy
Contrôle quelles browser features et APIs la page peut utiliser (remplace Feature-Policy).
# Désactiver les fonctionnalités dangereuses
Permissions-Policy:
geolocation=(),
microphone=(),
camera=(),
payment=(),
usb=(),
interest-cohort=()
Configuration par serveur
Nginx
# nginx.conf
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self';" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
Apache
# .htaccess ou httpd.conf
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self';"
Node.js/Express
// Utiliser le middleware Helmet
const helmet = require('helmet');
app.use(helmet());
// Configuration personnalisée
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-'"],
styleSrc: ["'self'", "'nonce-'"],
}
}));
Tester les Security Headers
- securityheaders.com : Scan et note A+
- Mozilla Observatory : Analyse complète
- Chrome DevTools : onglet Network → Headers
- curl :
curl -I https://example.com
Piges courants
- CSP trop permissive avec 'unsafe-inline' et 'unsafe-eval'
- HSTS sans includeSubDomains laisse les sous-domaines vulnérables
- En-têtes configurés mais non appliqués (flag always manquant)
- Ne tester que la homepage - les en-têtes doivent être sur toutes les pages
Checklist complète
- [OK] Content-Security-Policy stricte configurée
- [OK] HSTS avec max-age d'1 an + includeSubDomains
- [OK] X-Frame-Options : DENY ou CSP frame-ancestors
- [OK] X-Content-Type-Options : nosniff
- [OK] Referrer-Policy configurée
- [OK] Permissions-Policy désactivant les fonctionnalités non utilisées
- [OK] En-têtes testés sur securityheaders.com (note A+)
- [OK] CSP testée d'abord en report-only mode
