Aller au contenu
🔒 En-têtes de sécurité HTTP pour WordPress : guide de configuration complet

🔒 En-têtes de sécurité HTTP pour WordPress : guide de configuration complet

Votre site WordPress tourne, le plugin de sécurité est installé, mais un test sur securityheaders.com vous donne un F. Cela vous rappelle quelque chose?

Les en-têtes de sécurité HTTP sont une couche de protection invisible, souvent négligée même après avoir mis en place un pare-feu et une authentification à deux facteurs. Ils ne nécessitent pas de renouvellement de licence, ne sollicitent pas le serveur et bloquent des catégories entières d’attaques: du détournement de clic au vol de session. Et leur mise en place prend 10 minutes.

Voici, étape par étape, les en-têtes dont vous avez réellement besoin, comment les configurer via le fichier .htaccess, le fichier functions.php ou un plugin, et comment vérifier que la protection est active, et pas seulement affichée.

💡 Aperçu rapide:

  • Vérifiez les en-têtes actuels de votre site via securityheaders.com ou Mozilla Observatory pour avoir une vision réelle de la situation
  • Activez un jeu de base de 4 à 5 en-têtes: X-Content-Type-Options, X-Frame-Options, HSTS, Referrer-Policy, Permissions-Policy
  • Choisissez votre méthode: quelques lignes dans le fichier .htaccess (Apache/LiteSpeed), un extrait de code dans functions.php, ou le plugin Headers Security Advanced & HSTS WP
  • Laissez le CSP de côté pour le moment: sa configuration est délicate et il casse Gutenberg si elle est faite sans tests
  • Après la mise en œuvre, refaites le test: un score A+ est atteignable en 10 minutes

Ce que sont les en-têtes de sécurité HTTP

Lorsqu’un navigateur demande une page, le serveur web ne renvoie pas seulement du code HTML. Chaque réponse HTTP contient des champs de service, les en-têtes. Certains gèrent la mise en cache et le type de contenu, d’autres la sécurité.

Le navigateur lit les en-têtes de sécurité avant même de commencer à afficher la page. Si le serveur dit «j’interdis l’intégration de ce site dans des cadres», le navigateur ne le fera pas, même si le code de la page contient un <iframe>. Si le serveur dit «utilisez uniquement HTTPS pendant un an», le navigateur s’en souvient et n’ira pas sur la version HTTP, même si l’utilisateur la saisit manuellement.

Ni JavaScript, ni plugin, ni pare-feu n’interviennent ici. C’est le niveau du protocole. C’est précisément pour cette raison que les en-têtes constituent une ligne de défense distincte et indépendante.

Pourquoi un site WordPress en a besoin

Les plugins de sécurité comme Wordfence ou Solid Security corrigent les vulnérabilités au niveau applicatif: force brute, injections, téléversements malveillants. Les en-têtes HTTP agissent un niveau au-dessus: ils protègent le canal de communication lui-même entre le serveur et le visiteur.

Voici ce que bloquent des en-têtes correctement configurés:

  • Le détournement de clic. Un attaquant intègre votre site dans un cadre transparent superposé au sien et intercepte les clics des utilisateurs. Bloqué par l’en-tête X-Frame-Options ou la directive frame-ancestors dans le CSP.

  • Le reniflage MIME. Le navigateur tente de «deviner» le type de fichier et peut exécuter une image téléversée comme du JavaScript. Bloqué par X-Content-Type-Options: nosniff.

  • Le vol de session. Un attaquant sur un réseau Wi-Fi ouvert modifie la réponse du serveur et dérobe les cookies de connexion. HSTS interdit au navigateur d’accéder à la version HTTP du site.

  • La fuite de référent. Lorsque l’on suit un lien externe, le site de destination voit de quelle page l’utilisateur provient, y compris l’URL avec ses paramètres. Referrer-Policy limite cela.

  • L’accès non autorisé aux périphériques. Une page web demande le microphone, la caméra ou la géolocalisation à l’insu de l’utilisateur. Permissions-Policy bloque ces demandes au niveau du navigateur.

Le CSP ajoute une couche supplémentaire: vous définissez explicitement quels domaines peuvent charger des scripts, des styles et des polices. Même si du code malveillant parvient dans la base de données, le navigateur ne l’exécutera pas car la source n’est pas dans la liste d’autorisation. Mais le CSP exige de la prudence: une petite erreur, et l’éditeur Gutenberg cesse de fonctionner.

En-têtes de sécurité HTTP essentiels: contenu et intérêt

Voici les en-têtes qu’il est pertinent de configurer sur tout site WordPress. Pour chacun, nous précisons: l’attaque contre laquelle il protège, la valeur recommandée et les éventuels points de rupture.

X-Content-Type-Options

Le plus simple et le plus sûr à configurer. La seule valeur valide est nosniff. Le navigateur cesse de «deviner» le type MIME d’un fichier en se basant sur son contenu et se fie uniquement au type transmis par le serveur dans l’en-tête Content-Type.

Sans cet en-tête, le navigateur peut interpréter une image téléversée par un utilisateur comme un script et l’exécuter, un scénario classique d’attaque par téléversement de fichier.

Valeur recommandée: nosniff

Risques de rupture: minimes. Des problèmes ne sont possibles que si le serveur délivre des fichiers avec un Content-Type incorrect, mais c’est un problème distinct qu’il vaut mieux corriger plutôt que masquer.

X-Frame-Options

Contrôle si votre site peut être intégré dans un élément <frame>, <iframe> ou <object> sur un autre site.

Deux valeurs principales:

  • DENY, une interdiction totale d’intégration. Protection maximale.
  • SAMEORIGIN, l’intégration n’est autorisée que depuis le même domaine. Utile si vous utilisez vous-même des frames pour vos propres pages (par exemple, un aperçu dans l’interface d’administration).

Pour la plupart des sites WordPress, SAMEORIGIN convient. Si vous êtes certain qu’aucune frame n’est utilisée, passez à DENY.

Valeur recommandée: SAMEORIGIN

Risques de rupture: certains plugins utilisent des iframes pour les aperçus. Si quelque chose ne s’affiche plus dans l’administration après avoir activé DENY, repassez à SAMEORIGIN.

Strict-Transport-Security (HSTS)

Indique au navigateur: «pendant les N prochaines secondes, accède à ce domaine uniquement via HTTPS». Protège contre les attaques de rétrogradation et le détournement de cookies sur les réseaux ouverts.

Le paramètre clé est max-age. Il est recommandé de commencer par une valeur faible (un jour ou une semaine) et, après vérification, de l’augmenter à un an.

Le paramètre optionnel includeSubDomains étend la règle à tous les sous-domaines, ce qui est important si vous en avez plusieurs et utilisez un CDN.

Le paramètre preload ajoute le site à la liste HSTS globale des navigateurs: Chrome, Firefox et Safari accéderont à votre domaine uniquement via HTTPS avant même la première requête. Soumettez une demande via hstspreload.org.

Valeur recommandée: max-age=31536000; includeSubDomains

Risques de rupture: si vous activez HSTS et que le certificat SSL expire, les utilisateurs ne pourront plus du tout accéder au site. Surveillez le renouvellement automatique du certificat.

Referrer-Policy

Gère les informations sur la page d’origine que le navigateur transmet lorsqu’on suit un lien vers un autre site.

Valeurs principales, de la plus stricte à la plus permissive:

  • no-referrer, rien n’est envoyé.
  • strict-origin-when-cross-origin, vers un domaine différent, seul le domaine est envoyé (pas le chemin ni les paramètres); vers le vôtre, l’URL complète. L’équilibre optimal entre confidentialité et analytics.
  • strict-origin, toujours uniquement le domaine, jamais le chemin.

Si vous ne souhaitez pas que les sites de destination sachent d’où vient l’utilisateur, choisissez no-referrer. Mais gardez à l’esprit que vous perdrez le trafic de référence dans vos propres analytics.

Valeur recommandée: strict-origin-when-cross-origin

Risques de rupture: minimes. Certains services tiers peuvent exiger un referrer pour fonctionner (par exemple, des passerelles de paiement avec vérification de l’origine). Vous pouvez repérer ces cas via la console du navigateur.

Permissions-Policy

Anciennement appelé Feature-Policy. Restreint l’accès de la page web aux API «matérielles» du navigateur: microphone, caméra, géolocalisation, USB, API de paiement, etc.

Format: название-фичи=(разрешённый-источник). Par exemple:

1Permissions-Policy: camera=(), microphone=(), geolocation=(self)

Cet exemple bloque complètement l’accès à la caméra et au microphone pour toutes les sources, et n’autorise la géolocalisation que pour le site lui-même (self).

Liste complète des fonctionnalités sur MDN. Pour un site WordPress sans visioconférence ni fonctionnalités PWA, il suffit de bloquer la caméra, le microphone et la géolocalisation; le reste est optionnel.

Valeur recommandée: dépend des fonctionnalités du site. Minimum: camera=(), microphone=(), geolocation=(self).

Risques de rupture: si le site propose de la visioconférence, une PWA ou du WebUSB, vérifiez les fonctionnalités dont il a besoin et ne les bloquez pas.

Content-Security-Policy (CSP)

L’en-tête le plus puissant et le plus dangereux à configurer. Définit une liste blanche de sources pour les scripts, les styles, les polices, les images, les frames et d’autres ressources.

Exemple de politique minimale pour WordPress:

1Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;
2

Pourquoi unsafe-inline et unsafe-eval: WordPress, Gutenberg et des dizaines de plugins génèrent des scripts inline et utilisent eval(). Sans ces directives, l’interface d’administration ne fonctionnera tout simplement pas. C’est le prix de la compatibilité.

Recommandation: n’activez pas la CSP en premier. Configurez d’abord les 5 autres en-têtes. Ne mettez en œuvre la CSP que si vous disposez des ressources pour les tests et la supervision; commencez par le mode Content-Security-Policy-Report-Only et collectez les journaux de violation pendant quelques semaines avant de passer en mode application.

Risques de rupture: élevés. Une erreur dans la CSP peut casser complètement le frontend et l’administration. Testez toujours sur un environnement de staging ou via Report-Only.

Comment vérifier les en-têtes actuels de votre site

Avant de configurer, un audit. Trois outils, du plus simple au plus détaillé:

  • securityheaders.com, saisissez l’URL et obtenez une note de A+ à F avec un détail pour chaque en-tête. Gratuit, sans inscription.

  • Mozilla Observatory, un audit plus poussé: évalue non seulement les en-têtes mais aussi les paramètres TLS, les attributs de cookies, le CORS et d’autres aspects. Également gratuit.

  • Chrome DevTools, ouvrez l’onglet Network, sélectionnez n’importe quelle requête vers votre site et consultez la section Response Headers. Un moyen rapide de vérifier si les modifications ont bien été prises en compte après avoir modifié le.htaccess.

Vérifiez votre site dès maintenant. Si la note est inférieure à B, vous n’avez même pas les en-têtes de base, et un tiers des éléments ci-dessous se paramètrent en 5 minutes.

Façons de configurer les en-têtes HTTP dans WordPress

Trois chemins, du manuel à l’automatique. Choisissez en fonction de votre situation.

Méthode 1: via.htaccess (Apache/LiteSpeed)

La méthode la plus rapide pour les sites sous Apache ou LiteSpeed. Ajoutez au fichier .htaccess à la racine du site (avant # BEGIN WordPress):

1<IfModule mod_headers.c>
2 Header set X-Content-Type-Options "nosniff"
3 Header set X-Frame-Options "SAMEORIGIN"
4 Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"
5 Header set Referrer-Policy "strict-origin-when-cross-origin"
6 Header set Permissions-Policy "camera=(), microphone=(), geolocation=(self)"
7</IfModule>

L’enveloppe <IfModule mod_headers.c> garantit que le site ne plantera pas avec une erreur 500 si le module mod_headers n’est pas activé. Si vous savez avec certitude qu’il est actif, vous pouvez l’omettre.

Après avoir sauvegardé, exécutez dans le terminal (si vous avez WP-CLI) ou ouvrez simplement le site et vérifiez les en-têtes via securityheaders.com. Les modifications dans .htaccess s’appliquent instantanément; aucun redémarrage du serveur n’est nécessaire.

Méthode 2: via functions.php (Nginx / universel)

Fonctionne quel que soit le serveur web, convient aussi bien à Nginx qu’à Apache. Ajoutez au functions.php de votre thème enfant ou via l’extension Code Snippets:

1function sdstudio_add_security_headers() {
2 header( 'X-Content-Type-Options: nosniff' );
3 header( 'X-Frame-Options: SAMEORIGIN' );
4 header( 'Strict-Transport-Security: max-age=31536000; includeSubDomains' );
5 header( 'Referrer-Policy: strict-origin-when-cross-origin' );
6 header( 'Permissions-Policy: camera=(), microphone=(), geolocation=(self)' );
7}
8add_action( 'send_headers', 'sdstudio_add_security_headers' );

Le hook send_headers se déclenche avant que WordPress ne commence à envoyer du contenu, donc les en-têtes partent dans la toute première réponse du serveur.

Pour Nginx, cette méthode est préférable à fouiller dans la configuration du serveur (surtout sur un hébergement mutualisé, où l’accès à nginx.conf est souvent indisponible). L’inconvénient: les en-têtes ne fonctionnent que pour les requêtes PHP qui passent par WordPress. Les fichiers statiques (images, CSS, JS) sont servis directement par Nginx et ne recevront pas les en-têtes. Ils nécessitent une configuration au niveau du serveur.

Méthode 3: via l’extension headers security advanced & hsts wp

Si vous ne voulez pas toucher au code, utilisez une extension dédiée. Headers Security Advanced & HSTS WP rassemble tous les en-têtes de sécurité dans une seule interface et les active en un clic.

L’extension définit des valeurs prédéfinies pour tous les en-têtes clés immédiatement après l’activation: X-Content-Type-Options, X-Frame-Options, HSTS, CSP, Referrer-Policy, Permissions-Policy, et plusieurs autres (CORP, COOP, COEP). Chaque en-tête peut être désactivé ou personnalisé selon vos besoins.

L’avantage de cette approche: l’extension ne dépend pas du serveur web et fonctionne de manière identique sur Apache, Nginx, LiteSpeed et IIS. Lors de la désactivation, elle remet la configuration du site dans son état d’origine.

Alternative: Redirection

L’extension Redirection est connue comme un gestionnaire de redirections, mais elle peut aussi ajouter des en-têtes HTTP. Après l’installation et la configuration de base, allez dans la section Site → Headers; l’interface vous permet de spécifier n’importe quel couple «en-tête: valeur».

Cette option fonctionne si vous avez déjà Redirection installé pour la gestion des liens et que vous ne voulez pas ajouter une autre extension. Mais une extension dédiée aux en-têtes donne plus de contrôle et des valeurs prédéfinies.

Dans la vidéo, une démonstration visuelle de la configuration des en-têtes via l’extension Headers Security Advanced: de l’installation à la vérification du résultat sur securityheaders.com.

⁉️🤔 Questions fréquentes

Que faire si le site casse après l’activation des en-têtes?

D’abord, vérifiez l’en-tête Content-Security-Policy: c’est lui qui cause la grande majorité des casses. Désactivez CSP (ou passez-le en mode Report-Only) et vérifiez à nouveau le site. Une erreur 500 après avoir modifié.htaccess: vérifiez la syntaxe pour un espace en trop, des guillemets non fermés ou un module mod_headers manquant. Via FTP, renommez.htaccess, le site reviendra à la vie, et vous pourrez chercher l’erreur calmement.

Dans 9 cas sur 10, le problème vient spécifiquement de CSP, pas des autres en-têtes. X-Content-Type-Options, X-Frame-Options, HSTS et Referrer-Policy ne peuvent physiquement pas casser le site; ils n’affectent ni le rendu ni la logique PHP. Commencez toujours par ceux-là.

Une extension est-elle obligatoire, ou peut-on le faire via le code?

On peut et on doit le faire via le code si vous savez modifier functions.php ou.htaccess. Définir les en-têtes directement via la configuration du serveur fonctionne plus vite qu’une extension, sans couche PHP intermédiaire. Mais une extension est plus pratique pour ceux qui ne veulent pas toucher au code et offre une interface visuelle avec des préréglages pour chaque en-tête.

Sur nos sites de test, nous utilisons les deux approches: en production,.htaccess (moins de points de défaillance); sur les sites clients où l’hébergement ne permet pas de modifier la configuration, l’extension. Le résultat sur securityheaders.com est identique: A+ dans les deux cas.

Ai-je besoin de configurer CSP si le site est sous WordPress?

Pour la plupart des sites, non. CSP sur WordPress nécessite unsafe-inline et unsafe-eval pour que Gutenberg et des dizaines d’extensions fonctionnent, ce qui réduit l’effet protecteur à un niveau symbolique. Un CSP complet a du sens sur des projets à forte charge avec un spécialiste sécurité dédié qui analysera chaque rapport de violation. Pour tous les autres, les 5 en-têtes de base fournissent la part du lion de la protection pratique.

Comment vérifier que les en-têtes fonctionnent après l’installation?

Ouvrez le site dans un navigateur, lancez les DevTools (F12) → onglet Network → cliquez sur la première requête vers votre domaine → section Response Headers. Si vous voyez les en-têtes ajoutés, tout fonctionne. Pour une vérification automatisée, utilisez securityheaders.com: il montre non seulement la présence mais aussi la justesse des valeurs, plus un score final de A+ à F.

Que faire si l’hébergement ne permet pas de modifier.htaccess et qu’il n’y a pas d’accès à functions.php?

Installez Headers Security Advanced & HSTS WP via l’administration WordPress. L’extension injecte les en-têtes au niveau PHP et ne nécessite pas de modifier les fichiers du serveur. Cela fonctionne sur tout hébergement où WordPress tourne, du mutualisé économique au Managed WordPress.

Les en-têtes HTTP affectent-ils la vitesse du site?

Pratiquement pas. Les en-têtes représentent quelques dizaines d’octets de texte dans la réponse du serveur. Ils n’effectuent aucun calcul, ne font aucune requête en base de données et ne sollicitent pas le CPU. Le délai qu’ils ajoutent se mesure en microsecondes. La seule exception est CSP avec une liste blanche complexe de centaines de domaines: le navigateur passe du temps à l’analyser, mais même dans ce cas, l’impact sur la vitesse de rendu ne dépasse pas quelques millisecondes.

Que définir et par où commencer

Les en-têtes de sécurité HTTP ne sont pas une action ponctuelle «à configurer une fois pour toutes». Ils constituent une base qui devrait être présente sur chaque site par défaut, comme un certificat SSL.

Le plan pour aujourd’hui:

  • Vérifiez votre site sur securityheaders.com. Si le score est D ou F, vous n’avez même pas X-Content-Type-Options.

  • Ajoutez les 5 en-têtes de base en utilisant l’une des trois méthodes ci-dessus. Si le site est sous Apache, via.htaccess (30 secondes). Nginx sans accès à la configuration, via functions.php (2 minutes). Si vous ne voulez pas toucher au code, l’extension Headers Security Advanced (3 minutes installation comprise).

  • Revérifiez le site. Le score devrait monter à A ou A+.

  • Mettez CSP de côté. Revenez-y une fois que les en-têtes de base auront fonctionné un mois sans problème et que vous aurez le temps de tester via le mode Report-Only.

Une heure, et votre site WordPress gagne une couche de défense dont la grande majorité des sites sur Internet sont dépourvus. Commencez par une vérification dès maintenant.