En-têtes de sécurité WordPress : CSP, HSTS et plus
En-têtes de sécurité WordPress : valeurs de départ sûres pour HSTS, CSP, Referrer-Policy et Permissions-Policy, où les configurer et comment éviter les pannes.
Aussi en : English Deutsch Español Italiano Polski Português Türkçe
La plupart des sites WordPress peuvent corriger une mauvaise note d'en-têtes en moins d'une heure. Ajoutez dès aujourd'hui quatre en-têtes à faible risque : HSTS, X-Content-Type-Options, Referrer-Policy et Permissions-Policy. Déployez ensuite Content-Security-Policy progressivement, d'abord en mode « report-only ». Ce guide donne des valeurs de départ sûres pour chacun de ces en-têtes de sécurité WordPress, indique où les configurer et précise lesquels risquent de casser l'éditeur ou les contenus intégrés.
Ce que font les en-têtes de sécurité WordPress, et ce qu'ils ne font pas
Les en-têtes de sécurité sont des instructions que votre serveur envoie au navigateur du visiteur. Ils lui demandent de n'utiliser que HTTPS, de ne pas deviner le type des fichiers, de ne pas laisser d'autres sites afficher vos pages dans un cadre, et ils précisent quels scripts il peut exécuter. Ils réduisent ainsi les attaques par rétrogradation, le MIME sniffing, le clickjacking et l'impact des failles de type cross-site scripting (XSS).
Ils ne corrigent pas une extension vulnérable, n'arrêtent pas une attaque par force brute sur les mots de passe et ne protègent pas le serveur lui-même. Si un attaquant peut écrire des fichiers PHP sur votre serveur, aucun en-tête n'y changera rien. Considérez-les comme une couche de durcissement côté navigateur, pas comme un correctif de sécurité.
L'absence de ces en-têtes est un exemple classique de mauvaise configuration de sécurité dans le Top 10 de l'OWASP. Ce sont aussi des mesures peu coûteuses et bien documentées, qui relèvent de « l'état de l'art » que l'article 32 du RGPD demande de prendre en compte.
La base : des valeurs de départ sûres pour chaque en-tête
Ces valeurs sont volontairement prudentes. Elles ne devraient pas casser un site WordPress classique, et vous pourrez les durcir plus tard.
| En-tête | Rôle | Valeur de départ sûre |
|---|---|---|
| Strict-Transport-Security | Impose HTTPS lors des visites suivantes | max-age=300 |
| X-Content-Type-Options | Empêche la devinette du type MIME | nosniff |
| Referrer-Policy | Limite les données d'URL transmises aux autres sites | strict-origin-when-cross-origin |
| Permissions-Policy | Désactive les fonctions du navigateur inutilisées | camera=(), microphone=(), geolocation=() |
| Content-Security-Policy | Protection contre l'affichage en cadre (pour l'instant) | frame-ancestors 'self' |
| X-Frame-Options | Protection historique contre le cadrage | SAMEORIGIN |
HSTS est défini dans la RFC 6797. Commencez par cinq minutes (max-age=300) et vérifiez que rien ne casse. Passez ensuite à un jour (86400), puis à une semaine, et enfin à un an (31536000). N'ajoutez includeSubDomains qu'après avoir vérifié que chaque sous-domaine est servi en HTTPS.
Referrer-Policy : avec strict-origin-when-cross-origin, seul votre domaine est transmis aux autres sites, et non l'URL complète. Sur WordPress, cela compte, car les URL contiennent souvent des paramètres : termes de recherche, numéros de commande, paramètres de campagne. Mieux vaut qu'ils n'arrivent pas chez des tiers.
Permissions-Policy désactive la caméra, le microphone et la géolocalisation pour vos pages et pour tous les cadres intégrés. Si vous avez un localisateur de magasins qui a besoin de la position, retirez geolocation de la liste.
La protection contre le cadrage relève désormais de la CSP, avec frame-ancestors 'self'. Ne gardez X-Frame-Options: SAMEORIGIN que comme solution de repli pour les anciens navigateurs. Une petite CSP appliquée, qui ne contient que frame-ancestors, peut être déployée sans risque dès maintenant. La CSP complète viendra plus tard.
X-XSS-Protection est obsolète. Ne l'activez pas. Il pilotait un filtre XSS que les navigateurs modernes ont supprimé, et ce filtre pouvait lui-même être détourné pour créer de nouveaux problèmes sur des pages jusque-là saines. Envoyer 1; mode=block n'apporte rien. La CSP en prend la place.
Où définir les en-têtes de sécurité : serveur, extension ou CDN
Choisissez un seul endroit par en-tête. Si le serveur, une extension de sécurité et le CDN envoient tous Strict-Transport-Security, vous obtenez des valeurs en double ou contradictoires, et personne ne sait plus laquelle est active.
Le serveur web est généralement le meilleur endroit. Ses règles s'appliquent à toutes les réponses : images, fichiers CSS et pages servies depuis un cache de pages complet. Sur Apache, ce qui couvre la plupart des hébergements mutualisés, ajoutez ceci au fichier .htaccess à la racine de WordPress, au-dessus du bloc # BEGIN WordPress. Cela nécessite mod_headers :
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=300"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set X-Frame-Options "SAMEORIGIN"
</IfModule>
Sur nginx, placez les lignes équivalentes dans le bloc server de votre site HTTPS, puis lancez nginx -t avant de recharger la configuration :
add_header Strict-Transport-Security "max-age=300" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header X-Frame-Options "SAMEORIGIN" always;
Attention à un piège de nginx. Un bloc location qui contient sa propre ligne add_header n'hérite d'aucune ligne add_header du niveau server. Un en-tête de cache ajouté pour /wp-content/uploads/ peut ainsi supprimer sans bruit tous vos en-têtes de sécurité sur ces fichiers. Répétez les en-têtes dans ce bloc, ou placez-les dans un fragment que vous incluez partout avec include.
Les extensions et le code qui utilisent le hook send_headers de WordPress ne s'exécutent que lorsque PHP construit la page. Les fichiers statiques ne passent jamais par PHP. Les pages servies depuis un cache de pages complet peuvent elles aussi l'éviter, selon la façon dont le cache stocke et rejoue les en-têtes. Les règles de CDN ou de périphérie sont une bonne alternative, car elles couvrent tout ce qui transite par le CDN. Les hébergeurs gérés proposent souvent leurs propres réglages d'en-têtes dans le panneau de contrôle. Si c'est le cas du vôtre, utilisez ce panneau et ne dupliquez pas les règles dans .htaccess.
Content-Security-Policy sans casser WordPress
La CSP est l'en-tête qui apporte le plus de bénéfices, mais aussi le plus de risques. Elle indique au navigateur quelles sources de scripts, de styles, d'images, de polices et de cadres sont autorisées. WordPress complique la tâche. Le cœur et l'éditeur de blocs produisent des scripts et des styles en ligne. Les constructeurs de pages en injectent d'autres. Les outils d'analyse, les intégrations YouTube et cartes, les bandeaux de cookies et les widgets de paiement chargent chacun du code depuis d'autres domaines. Une politique stricte qui bloque l'un d'eux peut casser le paiement ou laisser un écran d'édition vide.
Commencez en mode « report-only ». Le navigateur consigne alors les violations sans rien bloquer :
Content-Security-Policy-Report-Only: default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'
Ouvrez vos principaux types de pages : accueil, article de blog, page avec contenu intégré, panier et paiement. Ouvrez ensuite les outils de développement du navigateur et consultez la console pour chacune. Chaque violation nomme la ressource bloquée et la directive enfreinte. Prenez cette liste comme un inventaire des requêtes tierces que fait votre site. Vous y trouverez souvent des éléments que plus personne ne se rappelle avoir ajoutés, comme un ancien widget de chat ou des polices chargées depuis Google. Notre article sur Google Fonts explique comment les traiter.
Ajoutez les sources dont vous avez réellement besoin, retirez les autres, puis vérifiez à nouveau la console. Ne remplacez le nom de l'en-tête par Content-Security-Policy que lorsque les violations ont cessé sur toutes les pages importantes. Incluez frame-ancestors 'self' dans cette politique complète : les navigateurs ignorent frame-ancestors en mode report-only, et l'en-tête complet remplacera le petit que vous avez posé plus tôt. Les scripts en ligne sont le point difficile : autoriser 'unsafe-inline' supprime une grande part de la protection contre le XSS, tandis que les nonces ou les hachages exigent la prise en charge du thème ou de l'extension. La référence CSP de MDN documente chaque directive.
Envisagez de laisser wp-admin en dehors de la politique stricte, au moins au début. Sur nginx, définissez la CSP du front-end dans les location qui servent le site public plutôt que dans tout le bloc server.
Vous pouvez ajouter un point de terminaison report-uri ou report-to pour centraliser les violations. Ces rapports contiennent des URL de pages et des informations sur le navigateur, et chacun arrive avec l'adresse IP du visiteur. Un service de rapports tiers agit généralement comme votre sous-traitant au sens du RGPD : il vous faut donc un contrat de sous-traitance (art. 28). Pour un petit site, lire vous-même la console suffit souvent.
Préchargement HSTS : pourquoi attendre
Le préchargement inscrit votre domaine sur une liste livrée avec les navigateurs. Ceux-ci utilisent alors HTTPS pour votre domaine dès la première visite, et pour chacun de ses sous-domaines. C'est là que se situe le problème. Un ancien serveur de messagerie web, un site de préproduction, l'interface d'une imprimante ou un outil d'intranet qui ne fonctionne qu'en HTTP simple deviennent inaccessibles dans ces navigateurs.
Retirer un domaine de la liste est possible, mais lent. Les navigateurs n'abandonnent l'entrée qu'une fois la modification parvenue aux utilisateurs par les mises à jour. Raisonnez comme si la décision était définitive.
Augmentez max-age par étapes et maintenez les valeurs élevées pendant un certain temps. Listez tous les sous-domaines utilisés par votre organisation, y compris ceux du DNS que plus personne ne visite. N'envisagez le préchargement que lorsqu'ils sont tous servis en HTTPS. Le site de soumission hstspreload.org publie les exigences en vigueur pour l'en-tête. Lisez-les là-bas plutôt que de recopier des valeurs trouvées dans des articles de blog.
Tester vos en-têtes et les maintenir en place
Vérifiez les réponses réelles, pas vos fichiers de configuration. Dans les outils de développement du navigateur, ouvrez l'onglet Réseau, cliquez sur la requête du document et lisez les en-têtes de réponse. Depuis un terminal :
curl -sI https://example.com/
curl -sI https://example.com/wp-includes/css/dist/block-library/style.min.css
Des sites publics de vérification d'en-têtes donnent un aperçu rapide. L'OWASP Secure Headers Project explique la logique de chaque en-tête recommandé. Testez au minimum ces cinq réponses :
- La page d'accueil
- Une page servie depuis le cache, ouverte sans être connecté
- Un fichier statique (CSS, JS ou image)
/wp-login.php- Un écran de wp-admin, y compris l'éditeur de blocs
Les en-têtes ont tendance à disparaître sans que personne ne le remarque. Les causes habituelles : une migration d'hébergeur qui perd vos règles .htaccess, un changement de CDN, ou une nouvelle extension de cache ou de sécurité qui envoie ses propres valeurs. Revérifiez les en-têtes après chacun de ces changements. Conservez la configuration active et la date du test avec vos autres documents de durcissement, issus de la checklist de sécurité. C'est ce document que vous présenterez à un client qui vous envoie un questionnaire, ou à un auditeur.
L'extension d'audit de secaudit.eu réalise une analyse de durcissement et de configuration, puis rattache ses constats à l'art. 32 du RGPD et à l'art. 21 de la directive NIS 2. Utilisez-la en complément des vérifications d'en-têtes ci-dessus → secaudit.eu
FAQ
Les en-têtes de sécurité influencent-ils le référencement ou la vitesse des pages ?
L'effet est négligeable. Ils ajoutent quelques centaines d'octets à chaque réponse. HSTS peut éviter la redirection de HTTP vers HTTPS lors des visites répétées.
Une extension peut-elle définir tous les en-têtes de sécurité à ma place ?
En partie. Une extension couvre les pages construites par PHP, mais peut manquer les fichiers statiques et les pages en cache. Les règles du serveur ou du CDN sont plus fiables.
Dois-je envoyer X-XSS-Protection: 0 ou l'omettre ?
Omettez-le, ou envoyez 0 si un questionnaire exige une valeur explicite. 0 désactive l'ancien filtre. N'utilisez jamais 1; mode=block.
HSTS est-il exigé par le RGPD ?
Aucune règle du RGPD ne nomme d'en-têtes précis. Le RGPD exige en revanche une sécurité appropriée, qui tienne compte de l'état de l'art. Imposer HTTPS avec HSTS est une mesure standard et peu coûteuse, qui s'inscrit dans cette exigence.
Cet article est une information générale et ne constitue pas un conseil juridique.
Vérifiez votre propre site
Security Audit & Compliance est l’extension WordPress de secaudit.eu : elle recherche les logiciels malveillants, le spam caché, les fichiers du cœur modifiés et le code vulnérable, et rattache ses constats à l’article 32 du RGPD, à l’article 21 de NIS2 et à l’OWASP Top 10.
Voir ce que vérifie l’extension