Gérer les en-têtes de sécurité d’un site wordpress

La protection d’un site WordPress ne se limite pas simplement à l’installation de certaines extensions de sécurité ou à la modification de l’URL de connexion.
Beaucoup d’attaques ciblent les navigateurs des utilisateurs plutôt que le serveur en lui-même. C’est à ce moment-là que les en-têtes de sécurité HTTP prennent effet.

Le serveur envoie ces en-têtes avec chaque réponse HTTP pour indiquer au navigateur comment traiter certains comportements essentiels : chargement de ressources, exécution de scripts, intégration via iframes, partage d’informations, et plus encore. S’ils sont bien configurés, ils permettent de :

Souvent sous-estimés ou mal configurés, ces en-têtes sont pourtant faciles à implémenter. Et surtout : ils n’imposent aucune surcharge à votre site tout en améliorant significativement la sécurité de vos visiteurs.
  • Prévenir des attaques XSS (cross-site scripting)
  • Prévenir le détournement d’identité (clickjacking)
  • Imposer l’emploi de connexions sécurisées via HTTPS.
  • Limiter les API du navigateur (par exemple, la caméra, la géolocalisation…)
Souvent sous-estimés ou mal configurés, ces en-têtes demeurent néanmoins faciles à mettre en place. Et surtout : ils n’imposent aucune surcharge sur votre site tout en renforçant considérablement la sécurité de vos visiteurs.
Nous allons expliquer en détail la mise en place de ces en-têtes, que vous utilisiez Apache (par le biais du fichier .htaccess) ou Nginx (grâce au fichier nginx.conf).

Comment mettre en place ces en-têtes, C’est ce que je vais essayer de vous exposer de la manière la plus précise possible.

Phase initiale: Préparer l’examen de l’environnement.

Avant d’apporter des modifications, il est primordial de comprendre l’environnement dans lequel notre site WordPress évolue. Avec ces données, vous allez rapidement saisir ce qui cloche ou pourquoi certaines choses se produisent.

Pour commencer, créons un fichier info.php qui nous fournira des détails cruciaux sur le serveur accueillant votre site internet.
Générer le fichier info.php
Procédure simple à l’aide de Bloc-notes (Windows) ou d’un éditeur de texte (Linux/macOS) :
Ouvrez l’éditeur de texte, qu’il s’agisse de Bloc-notes, Gedit, Sublime Text ou d’un autre.
Copier et coller ce code :
<?php
phpinfo();
?>
Nommez le fichier précisément info.php lors de son enregistrement.
Forme : Tous les fichiers
Codage : UTF-8 (préféré).
C’est le moment de l’envoyer vers votre site internet:
Pour un tutoriel détailler sur l’interface de FileZilla Aller directement sur le wiki. ICI

La procédure avec FileZilla :
Consultez le site suivant pour télécharger et installer FileZilla : https://filezilla-project.org
Démarrez FileZilla.
Dans la partie supérieure, veuillez saisir vos identifiants de connexion :
Hôte : l’adresse de votre domaine (par exemple, ftp.votresite.fr) ou l’adresse IP du serveur.
Identifiant : attribué par votre fournisseur d’hébergement.
Mot de passe : celui établi pour la connexion FTP/SFTP.
Port : 21 pour FTP et 22 pour SFTP (si activé).
Cliquez sur la connexion rapide.
filezilla

Transférer le fichier info.php

Placez le fichier info.php dans le dossier principal de votre site WordPress :

Selon l’hébergeur, le répertoire est souvent appelé /www, /htdocs ou /public_html.

On peut facilement l’identifier à la présence des trois dossiers logique de wordpress: wp-content, wp-admin, wp-includes.

Maintenant, nous allons rendre visite à ce fichier

https://votresite.fr/info.php

Visitez :

Noter les informations utiles !

Avant de mettre en place des politiques de sécurité, il est crucial d’avoir une compréhension exacte de la configuration de votre serveur. Voici une liste des éléments à examiner sur la page info.php, ainsi que l’importance de chacun d’eux :
  • Version de PHP utilisée (ex : PHP 8.3.21, c’est la version que je recommande au moment où j’écris ces mots) :
    Vérifiez que votre version de PHP est à jour et supportée. Les versions obsolètes comme PHP 5.6, 7.0, 7.1 ou même 7.4 ne reçoivent plus de mises à jour de sécurité.
    Utiliser une version obsolète expose votre site à des failles connues et souvent automatisées
  • Serveur web employé (Apache, Nginx, LiteSpeed, etc.) :
    Cette donnée vous informe sur le genre de serveur HTTP qui fait fonctionner votre site. C’est crucial, puisqu’il existe une variété de méthodes et de configuration des en-têtes propres à chaque serveur :
    Apache se sert habituellement du fichier .htaccess, qui est positionné à la racine du site, pour insérer des « headers » grâce à la directive Header set (si le module mod_headers est en marche).
    Nginx ne prend pas en charge la configuration à l’aide de fichiers .htaccess. Il vous faut modifier les fichiers de configuration (nginx.conf ou vhost spécifique) en utilisant add_header, dans les sections server ou location.
    LiteSpeed, fréquemment utilisé sur des hébergements mutualisés de qualité, est généralement compatible avec la majorité des directives .htaccess d’Apache, y compris celles relatives aux en-têtes de sécurité.
  • Cloudflare, proxy ou CDN : si vous employez un proxy inverse1 ou un CDN2, certains headers pourraient être altérés, négligés ou répétés. Il sera nécessaire de les configurer à la fois sur le serveur d’origine et parfois directement dans l’interface du CDN (tels que Cloudflare, Sucuri, etc.).
    Assurez-vous également de savoir si votre hébergement est partagé ou dédié : sur un hébergement mutualisé, l’accès se limite généralement au fichier .htaccess, alors que sur un VPS ou un serveur dédié, vous aurez la possibilité d’intervenir plus profondément dans les fichiers du serveur.
    Assurez-vous que vous n’avez pas un serveur proxy (comme Cloudflare, etc.) qui pourrait perturber les headers.

Modules actifs
(ex : mod_headers)

Dans le contexte d’Apache, les modules représentent des éléments supplémentaires qui offrent la possibilité d’élargir les fonctionnalités du serveur web. Certains sont indispensables au bon fonctionnement des en-têtes HTTP.
Module principal nécessaire pour ce guide :
mod_headers : il autorise l’ajout, la modification ou la suppression d’en-têtes HTTP à travers .htaccess. En son absence, des instructions telles que Header set seront négligées.
Comment vérifier les modules activés (en SSH) :
apachectl -M

Fichier de configuration PHP actif
(Loaded Configuration File)

Ceci vous présente le fichier php.ini qui est effectivement utilisé. Chaque directive PHP globale y est précisée.
Pas essentiel, mais si vous désirez vous pouvoir parfaitement :
Désactiver la visualisation des erreurs (display_errors = Off)
Masquer la version de PHP (expose_php est désactivé)
Restreindre les ressources (upload_max_filesize, post_max_size, memory_limit)

Extensions PHP installées :

Ces modules intègrent des fonctionnalités propres à PHP. Seuls quelques-unes sont importantes :
openssl, curl, json, mbstring, pdo_mysql et fileinfo
Pour WordPress : zip, gd ou imagick sont également bénéfiques. ( mais pas obligatoire)

Si elles ne sont pas indispensables, d’autres extensions moins courantes pourraient rendre votre serveur vulnérable à des failles de sécurité :
ftp : donne la possibilité d’effectuer des connexions FTP à partir de PHP. Aujourd’hui, elle est très dangereuse. C’est une aubene pour les hackers, elle est alors utilisée pour envoyer des fichiers non autorisés.
–imap : sert à lire des boîtes de courriels par le biais de PHP. Risque d’exposition à des attaques par injection ou configurations incorrectes.
ldap : pour effectuer des requêtes sur un annuaire LDAP. Une extension puissante, mais souvent peu pratique sur un site WordPress standard, elle peut devenir vulnérable si elle n’est pas correctement configurée.
Exif : utilisée pour l’analyse des métadonnées intégrées dans les images. Peut être exploitée lors d’attaques par des images malformées (attaque via exif_read_data).
sockets : autorise les liaisons réseau de bas niveau. Rarement employée dans un contexte web standard, elle peut cependant ouvrir des portes réseau imprévues.
L’activation d’une extension inutile élargit la surface d’attaque.

Attention : cette page info.php peut également révéler des chemins absolus, des noms de fichiers sensibles, voire la structure exacte de votre serveur. Elle ne doit jamais rester accessible.

Pensez à supprimer ce fichier après usage : « info.php » donne beaucoup d’informations sensibles !

en-têtes de sécurité

Comprendre les en-têtes de sécurité

Les en-têtes de sécurité ont une importance cruciale pour la protection de votre site WordPress. Ces éléments ne sont pas perceptibles par les utilisateurs, cependant ils déterminent la manière dont le navigateur doit réagir aux ressources, scripts et intégrations de tiers. S’ils ne sont pas correctement configurés, ils pourraient rendre votre site vulnérable à des failles sévères. Lorsqu’ils sont correctement mis en œuvre, ils fonctionnent comme un bouclier invisible, neutralisant de nombreuses attaques avant qu’elles ne parviennent à vos scripts PHP ou à vos formulaires.
Dans cette partie, nous examinerons les principaux en-têtes de sécurité HTTP : leur rôle précis, les paramètres conseillés, les valeurs à proscrire et les erreurs fréquentes à éviter. On accordera une attention spéciale à leur adéquation avec WordPress, les constructeurs de pages et les extensions populaires.
Empêche le chargement de scripts ou ressources non autorisés (anti-XSS, injection de contenu, etc.).
Exemple basique :
Content-Security-Policy: default-src 'self'; script-src 'self'
Paramètres recommandés :
  • default-src : définit la source par défaut (ex. ‘self’)
  • script-src : contrôle les scripts autorisés (local, CDN, etc.)
  • style-src, img-src, font-src : même principe pour CSS, images, polices
  • frame-ancestors : empêche l’affichage dans une iframe tierce
  • object-src ‘none’ : désactive les plugins obsolètes (Flash, etc.)
À éviter si possible :
unsafe-inline‘ : autorise les scripts inline (dangereux sans nonce3).
–Ce paramètre est malheureusement parfois nécessaire si votre site utilise des plugins qui injectent dynamiquement du JavaScript ou du CSS inline, comme :
Elementor (builder visuel)
WPBakery Page Builder (shortcodes et composants inline)
Slider Revolution (animations via <script> inline)
Fluent Forms (validation et logique conditionnelle dynamique)
WooCommerce avec certains addons personnalisés

—Laisser 'unsafe-inline' activé sans contrôle représente une faille XSS potentielle.
Il est préférable d’utiliser des nonce générés dynamiquement avec WordPress pour chaque requête si ces plugins doivent être conservés.
'unsafe-eval' : permet l’exécution dynamique de code JS (très risqué).
Bonnes pratiques :
–Utiliser des nonce ou sha256 pour autoriser des scripts spécifiques
–Éviter les politiques trop permissives qui rendent CSP inutile
Force les navigateurs à utiliser exclusivement le protocole HTTPS.
Exemple recommandé :
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Détails des options :
max-age=63072000 : durée de validité (en secondes, ici 2 ans)
includeSubDomains : applique la politique aux sous-domaines
preload : demande l’inclusion dans la liste HSTS des navigateurs majeurs
À ne pas utiliser si :
Votre site n’est pas entièrement en HTTPS
Vos sous-domaines ne sont pas encore migrés en HTTPS
Astuce : vérifiez bien que tous les liens internes pointent en https://
Cet en-tête de sécurité est un moyen essentiel de défense contre les attaques par injection MIME, aussi appelées « content-sniffing« .
Par défaut, certains navigateurs essaient de « deviner » le type de fichier (par exemple, interpréter un fichier .txt contenant du code JavaScript comme un fichier .js) même si le type MIME envoyé par le serveur est incorrect ou absent.
Cela peut entraîner l’exécution de scripts malveillants ou le téléchargement de contenus non prévus comme s’ils étaient sûrs, ce qui représente un vecteur d’attaque potentiel.
Notamment si des fichiers sont accessibles depuis un répertoire d’upload.
Valeur recommandée (et unique) :
X-Content-Type-Options: nosniff
Cette directive oblige le navigateur à respecter strictement le type MIME retourné par le serveur, et à ne pas tenter de le corriger ou de l’interpréter autrement.
À éviter :
Toute autre valeur ou l’absence de cette directive.
Certains développeurs la désactivent à tort en pensant corriger des problèmes d’affichage,
alors qu’il s’agit souvent d’un souci de configuration de serveur ou de cache.
Ce header est :
Léger à implémenter
Compatible avec tous les navigateurs modernes
Sans impact négatif sur les performances ou les fonctionnalités du site
Il doit toujours être activé sur tout site web, sans exception.
Cet en-tête est élaboré pour sécuriser votre site face aux tentatives d’attaques par clickjacking.
Le clickjacking est une technique frauduleuse visant à tromper un utilisateur en présentant votre site dans une iframe transparente sur un site nuisible, dans le but de le pousser à cliquer sur des éléments de votre interface sans qu’il s’en rende compte (comme un bouton de paiement, une case de consentement, etc.).
Avec X-Frame-Options, vous avez la possibilité de empêcher que votre site soit affiché dans des iframes sur d’autres domaines.

Valeurs possibles :
X-Frame-Options: DENY
Interdit toute intégration dans une iframe, quel que soit le domaine.
X-Frame-Options: SAMEORIGIN
L’attribut HTML sandbox a été introduit en 2010, avec la spécification HTML5. Il a été conçu pour renforcer la sécurité des iframes en isolant leur contenu du reste de la page.
Le sandbox est une fonctionnalité HTML/JavaScript côté navigateur, non côté serveur
Autorise l’intégration dans une iframe seulement si la page parent est sur le même domaine.
À éviter :
Ne pas définir cet en-tête du tout : par défaut, le site peut être affiché dans n’importe quel contexte iframe, ce qui expose à des attaques par clickjacking.
Utiliser ALLOW-FROM uri : cette directive permet de définir une exception, mais elle est obsolète et non supportée par Chrome et la plupart des navigateurs modernes.
Bon à savoir :
Certains plugins WordPress ou intégrations nécessitent l’affichage d’une iframe (par exemple : vidéos YouTube, widgets de réservation, contenu externe embarqué).
Dans ces cas, une politique trop restrictive (DENY) peut casser certaines fonctionnalités.
Pour plus de flexibilité, il est recommandé d’utiliser à la place une politique moderne via Content-Security-Policy et la directive frame-ancestors, qui permet un contrôle plus granulaire des domaines autorisés.
Utilisez SAMEORIGIN comme valeur par défaut si votre site inclut des iframes internes. Sinon, privilégiez DENY pour une protection maximale.
ce header peut entrer en conflit avec des widgets ou des vidéos embarquées.!

Autres autorisations possibles dans les iframes (via l’attribut HTML sandbox ) dans la page web elle même :
En complément de X-Frame-Options, l’attribut HTML sandbox de la balise <iframe> permet de restreindre ou d’autoriser certains comportements spécifiques de l’iframe. Voici les options les plus courantes :
allow-same-origin : permet au contenu de l’iframe d’être traité comme provenant de la même origine que la page parent. Sans cette option, l’iframe est traitée comme provenant d’un domaine totalement externe (même si c’est le même site).
allow-downloads : autorise les téléchargements depuis l’iframe.
allow-scripts : autorise l’exécution de JavaScript dans l’iframe.
allow-popups : autorise l’ouverture de fenêtres ou d’onglets via window.open().
allow-forms : autorise l’utilisation de formulaires dans l’iframe.
allow-top-navigation : autorise l’iframe à rediriger la fenêtre parent (via parent.location).
allow-pointer-lock : permet de capturer le curseur pour certaines interactions avancées.
allow-orientation-lock : autorise le blocage de l’orientation d’écran (notamment sur smartphone ou tablette).
allow-presentation : autorise le lancement d’une session de présentation (par exemple via un projecteur ou un autre écran connecté).
Ces autorisations peuvent être combinées dans l’attribut sandbox de l’iframe :
L’en-tête Referrer-Policy permet de contrôler ce que le navigateur inclut dans l’en-tête HTTP Referer lorsqu’un utilisateur clique sur un lien ou qu’un contenu externe est chargé.
Cela peut inclure des chemins internes sensibles, des identifiants de session ou des paramètres URL confidentiels.
Sans configuration explicite, les navigateurs transmettent parfois des informations complètes, exposant involontairement des données à des tiers (comme des régies publicitaires, des CDN, ou des services de tracking externes).
Objectif : réduire les risques de fuite d’informations internes lors d’une navigation inter-domaine ou du chargement de ressources tierces.
Valeur recommandée :
Referrer-Policy: strict-origin-when-cross-origin
–Si l’utilisateur clique sur un lien vers un site externe, seule l’origine (ex. : https://monsite.fr) est transmise.
Si la navigation reste sur le même domaine, l’URL complète peut être envoyée pour assurer la compatibilité analytique.
Autres valeurs et leur usage :
no-referrer : ne jamais transmettre de référent – idéal pour un anonymat total.
origin : transmet seulement le schéma et le domaine (ex. https://mon-site.com).
same-origin : ne transmet le référent que si la navigation reste sur le même domaine.
unsafe-url : transmet toujours l’URL complète, même vers des tiers — fortement déconseillé.
Bonnes pratiques :
Évitez de transmettre des paramètres sensibles via les URL (ex : jetons, ID utilisateur).
Utilisez une politique stricte si vous avez un site gouvernemental, bancaire ou à contenu protégé.
Combinez avec Content-Security-Policy pour une protection renforcée contre les fuites de données via le navigateur.
Referrer-Policy est un outil essentiel pour protéger la vie privée de vos visiteurs et éviter les fuites accidentelles de données internes.
Anciennement appelée Feature-Policy ou même Permissions-Policy permet de gérer l’accès aux API sensibles du navigateur pour une page web ou ses iframes.
Cela inclut : La caméra, le micro, la géolocalisation, les paiements, les capteurs et bien plus.
Cet en-tête est crucial pour empêcher un contenu tiers ou un script compromis d’accéder à des fonctionnalités critiques du navigateur.
Exemple de politique restrictive :
Permissions-Policy: camera=(), microphone=(), geolocation=()
Cela bloque entièrement l’accès à ces trois fonctionnalités pour toutes les origines.
Principaux paramètres disponibles :
camera=() / microphone=() / geolocation=() : blocage total ou restriction à des domaines spécifiques
fullscreen=() : empêche le mode plein écran
accelerometer=() / gyroscope=() / magnetometer=() : bloque les capteurs des appareils mobiles
payment=() : désactive les API de paiement web
autoplay=() : empêche la lecture automatique des médias
clipboard-write=() : interdit l’écriture dans le presse-papier
usb=() / bluetooth=() / serial=() : bloque les accès aux périphériques
Exemple plus permissif et contrôlé :
Permissions-Policy: geolocation=(self "https://maps.trusted.fr")
Cela autorise uniquement votre propre domaine + un service tiers précis à utiliser la géolocalisation.
À éviter :
Omettre complètement cet en-tête : cela revient à laisser tout activé par défaut, même si votre site n’utilise aucune de ces fonctions.
Ajouter des permissions inutiles qui augmentent la surface d’attaque, surtout sur un site vitrine ou institutionnel.
Bonnes pratiques :
Activez uniquement ce dont votre site a besoin.
Testez vos pages avec les outils développeur → onglet « Application » > « Permissions »
Intégrez cet en-tête même si vous ne chargez pas d’iframe : il protège aussi les scripts internes.

Conclusion : les en-têtes HTTP, en bref

Strict-Transport-Security (HSTS) : empêche les connexions non sécurisées, protège contre les attaques de type downgrade (HTTPS → HTTP).
Content-Security-Policy : bloque les scripts, objets, styles ou images non autorisés, empêche les injections XSS et les appels malveillants.
X-Content-Type-Options : empêche l’exécution de fichiers détournés via changement de type MIME.
X-Frame-Options : empêche les attaques de clickjacking sur l’interface visible de votre site.
Referrer-Policy : contrôle les informations que l’utilisateur transmet d’une page à l’autre (préserve la vie privée).
Permissions-Policy : limite l’accès aux capteurs, à la caméra, au micro ou à la géolocalisation de l’utilisateur.
Content-Security-Policy (encore elle) : en bloquant les scripts dangereux, elle protège les visiteurs et le backend WordPress.
Permissions-Policy : empêche un contenu embarqué malveillant d’interagir avec l’utilisateur et d’utiliser le contexte de session du site principal.
sandbox (iframe) : isole totalement les contenus externes, empêche leur interaction avec le reste du DOM.
Conclusion : chaque en-tête contribue à une couche de sécurité. Mais c’est leur combinaison bien pensée qui crée un véritable bouclier de protection globale.
Les en-têtes de sécurité HTTP ne se contentent pas d’améliorer votre score sur des outils comme SecurityHeaders ou Mozilla Observatory. Ils jouent un rôle concret et combiné dans la protection de votre site WordPress, de vos données, et de vos visiteurs.
  1. Un proxy inverse désigne un serveur placé devant les serveurs web et transmettant les requêtes des clients (par exemple, les navigateurs web) à ces serveurs web. Les solutions de proxy inverse sont généralement déployées pour améliorer la sécurité, les performances et la fiabilité. ↩︎
  2. Un réseau de diffusion de contenu (CDN pour content delivery network) est un groupe de serveurs répartis géographiquement qui met en cache le contenu à proximité des utilisateurs finaux.  ↩︎
  3. Un nonce (abréviation de number used once) en PHP est une valeur cryptographiquement unique et temporaire utilisée pour valider l’authenticité d’une requête. Dans le contexte de WordPress, un nonce permet de s’assurer qu’une action est bien initiée par un utilisateur légitime du site et non par un script malveillant (attaque CSRF – Cross Site Request Forgery). ↩︎

Laisser un commentaire