Un audit de reconnaissance externe commence presque toujours par la même commande, anodine en apparence : curl -I https://exemple.fr. Cette simple requête, qui ne récupère que les en-têtes de la réponse sans télécharger la page, en dit souvent davantage sur l’infrastructure d’un site que des heures de scan actif. Sur nombre de sites WordPress encore aujourd’hui, cette commande révèle la version exacte de PHP, le logiciel serveur utilisé et parfois même le système d’exploitation sous-jacent, toutes ces informations étant transmises sans qu’aucune configuration explicite ne l’ait demandé.
Cette checklist se concentre sur les en-têtes de réponse eux-mêmes, ceux que le serveur envoie au navigateur, à ne pas confondre avec les en-têtes de sécurité applicative comme la Content Security Policy ou HSTS, qui répondent à un objectif différent et ont déjà fait l’objet d’un article dédié sur ce blog. Il s’agit ici de réduire ce qu’un attaquant peut apprendre passivement, avant même de tenter la moindre action offensive.
Ce que révèlent les en-têtes par défaut
Sur une installation WordPress standard, hébergée sur une pile Apache ou Nginx classique, une requête curl -I renvoie fréquemment ces informations :
| En-tête | Ce qu’il révèle |
|---|---|
X-Powered-By | Version exacte de PHP, par exemple PHP/8.1.27 |
Server | Logiciel serveur et parfois sa version, par exemple Apache/2.4.57 (Debian) |
X-Generator | Confirmation explicite de l’usage de WordPress, ajoutée par certains thèmes ou extensions |
Aucune de ces informations n’est indispensable au fonctionnement du site. Elles servent uniquement, pour un attaquant en phase de reconnaissance, à cibler plus vite les vulnérabilités connues correspondant précisément à cette version de PHP ou de serveur, plutôt que de tester à l’aveugle une liste de failles génériques.
Filtrer côté serveur web plutôt qu’en PHP

Il est possible de masquer X-Powered-By en PHP avec header_remove('X-Powered-By'), mais cette approche présente un défaut : elle s’exécute après que PHP ait déjà décidé d’ajouter l’en-tête, et certaines configurations (erreurs précoces, pages générées hors du cycle normal de WordPress) peuvent laisser passer l’en-tête malgré tout. La bonne pratique consiste à désactiver l’ajout à la source, dans la configuration de PHP elle-même, via php.ini ou une directive équivalente :
# Dans php.ini ou un fichier .user.ini
expose_php = Off
Sur Nginx, le nom et la version du serveur s’effacent avec une directive globale, à placer dans le bloc http de la configuration principale :
http {
server_tokens off;
}
Sur Apache, deux directives combinées suffisent, généralement placées dans httpd.conf ou un fichier de configuration global (elles n’ont pas d’effet dans un .htaccess) :
ServerTokens Prod
ServerSignature Off
ServerTokens Prod réduit l’en-tête Server à la seule mention Apache, sans numéro de version ni système d’exploitation. ServerSignature Off supprime la ligne de signature qu’Apache ajoute par défaut au bas des pages d’erreur générées par le serveur lui-même (404, 500), qui révèle souvent les mêmes informations dans le corps de la réponse plutôt que dans un en-tête.
Le cas particulier des pages d’erreur et des sous-domaines de développement
Les pages d’erreur générées directement par le serveur web, avant même que WordPress n’intervienne, méritent une vérification séparée : une erreur 500 mal configurée peut afficher un chemin de fichier complet du serveur, une trace d’exécution PHP, ou une bannière de version. Sur un environnement de développement accessible via un sous-domaine de type *.dev.exemple.fr, ce risque est souvent plus élevé parce que WP_DEBUG_DISPLAY y reste activé plus longtemps qu’en production.
- Vérifier que
display_errorsest désactivé en production, même sur les sous-domaines de recette accessibles publiquement. - Personnaliser les pages d’erreur 404 et 500 pour qu’elles ne renvoient qu’un message générique, sans détail technique.
- Confirmer, avec
curl -I, qu’aucun en-têteX-Powered-ByniSerververbeux ne subsiste après modification, y compris derrière un CDN ou un reverse proxy qui pourrait réintroduire ses propres en-têtes.
Vérifier après un changement d’infrastructure
Ce filtrage se perd facilement lors d’une migration d’hébergeur, d’un changement de version de PHP géré par un panneau de contrôle, ou de l’ajout d’un CDN qui réécrit certains en-têtes à son tour. Il est utile d’intégrer une vérification simple dans le processus de mise en production :
curl -sI https://exemple.fr | grep -Ei 'x-powered-by|^server:|x-generator'
Une commande qui ne renvoie rien confirme que le filtrage est effectif. Sur un parc de plusieurs sites, ce contrôle se scripte facilement en boucle sur une liste de domaines, pour détecter d’un coup d’œil les serveurs qui auraient régressé après une mise à jour système.
Masquer un en-tête ne corrige aucune faille, mais retire à l’attaquant une information gratuite qui lui aurait fait gagner du temps. C’est un filet, pas un rempart.
Checklist à retenir
Trois vérifications suffisent pour couvrir l’essentiel de ce risque : désactiver expose_php dans la configuration PHP, appliquer ServerTokens Prod et ServerSignature Off sur Apache ou server_tokens off sur Nginx, et confirmer par une commande curl -I périodique que rien ne réapparaît après un changement d’infrastructure. Ce n’est pas une mesure de sécurité à elle seule, mais elle retire à un attaquant en phase de reconnaissance une part significative des informations qu’il obtiendrait autrement gratuitement, avant même d’avoir tenté quoi que ce soit.