Sécurité WordPress : audit et gestion de la liste blanche (allowlist)
Quand on parle de sécurité WordPress, on finit presque toujours par évoquer des plugins, des mises à jour, des rôles et des mots de passe. Tout cela compte, bien sûr. Mais, dans la pratique, beaucoup d’incidents ne commencent pas par “un plugin malveillant inconnu”, ils commencent par une dérive plus subtile : des chemins d’exécution inattendus, des fichiers qui apparaissent là où ils ne devraient pas, des scripts qui se déclenchent au bon endroit, au bon moment, avec une légitimité falsifiée. C’est précisément là que l’audit et la liste blanche (allowlist) deviennent un levier très concret.
Une allowlist, ce n’est pas “tout bloquer”. C’est choisir à l’avance ce qui est autorisé, puis refuser le reste, au moins pour les surfaces les plus sensibles. Bien utilisée, elle réduit l’espace d’attaque et rend les intrusions plus difficiles à stabiliser, même si un vecteur passe à travers les contrôles traditionnels.
Comprendre ce que protège vraiment une liste blanche
Une liste blanche peut s’appliquer à plusieurs niveaux dans un système WordPress. Le point d’attention, c’est qu’elle doit coller à la réalité de votre installation, sinon elle devient une source de pannes.
Il y a trois zones qui reviennent souvent dans les audits.
D’abord, les fichiers et répertoires. Un shell PHP, un fichier .txt servant de commande, un script dans wp-content ou dans un dossier inattendu, ce sont des choses qui se repèrent plus vite quand on sait ce qu’on devrait avoir. Ensuite, les requêtes HTTP ou les endpoints. Certains fichiers ne devraient jamais être appelés directement. Enfin, l’exécution côté PHP: des fonctions “dangereuses” ou des comportements non attendus (par exemple l’écriture de fichiers ou des appels réseau) peuvent être surveillés ou restreints selon l’outil utilisé.
Selon votre stack, l’allowlist peut être mise en œuvre via un pare-feu applicatif (WAF), un moteur de règles (selon votre hébergement), un contrôle de fichiers, ou un durcissement PHP. Dans tous les cas, la philosophie reste identique: identifier ce qui est normal chez vous, puis le figer.
L’important, c’est que la liste blanche soit construite après un audit et sécurisation WordPress qui part du réel, pas d’une liste générique.
Avant l’allowlist: l’audit qui évite de “verrouiller au mauvais endroit”
On peut faire une allowlist sans audit, mais on finit presque toujours par la regretter. Les sites vivants changent, les thèmes évoluent, les plugins ajoutent des endpoints, certains générateurs créent des fichiers en masse (images dérivées, caches, exports). Une allowlist appliquée trop tôt bloque des mécanismes légitimes, puis on la “corrige” dans la douleur. La sécurité recule, la maintenance explose.
Un audit utile commence par des questions simples, et par des preuves.
Que se passe-t-il réellement au moment où le site fonctionne “normalement”, sans charge d’attaque ? Quelles extensions chargent quoi, et où ? Quels répertoires reçoivent de nouveaux fichiers en dehors d’un déploiement officiel ? Quelles URL retournent quoi, et quelles routes sont réellement exposées ?
Sur le terrain, je recommande de prendre un instantané de l’état de référence. Pas une photo parfaite, une base de travail. Par exemple, une capture des versions de plugins et thème, la liste des fichiers au moins dans wp-content et la structure des dossiers, et les principaux réglages (droits, config, paramètres du serveur applicatif).
Ensuite, l’audit doit inclure des signaux d’intégrité. Sans affirmer des choses invérifiables, on peut rechercher des patterns défensifs : fichiers récents en dehors des routines habituelles, modifications sur des fichiers critiques, présence de scripts PHP là où il n’y en a pas, et comportements réseau non attendus. On peut aussi analyser les logs web et PHP, en cherchant des requêtes répétées, des URL anormales, ou des erreurs qui “sentent” un test d’exploitation.
Ce travail a une utilité directe: il sert à construire l’allowlist de manière réaliste, avec des exceptions justifiées. Une allowlist qui inclut le “juste assez” réduit la surface, mais ne détruit pas la production.
Construire l’allowlist à partir de votre “normalité”
Une allowlist pertinente ne ressemble pas à une liste de “toutes les bonnes pratiques”. Elle ressemble à votre site, à son cycle de vie, et à ses dépendances.
Sur un WordPress standard, la normalité se décline souvent ainsi.
Dans wp-content, ce que vous acceptez, c’est principalement des thèmes, des plugins, des uploads, des caches produits par des plugins (selon leur nature), et éventuellement des dossiers de build si vous utilisez un processus d’assets. Pour les uploads, le normal, c’est une arborescence et des noms générés par WordPress. Pour les caches, c’est plus variable, mais souvent localisé.
Côté code, les autorisations “normales” sont liées aux fichiers chargés. Vous avez un point central: l’exécution de PHP. Une allowlist à ce niveau est plus subtile à mettre en place, parce qu’elle dépend de votre serveur et des outils. Mais on peut déjà appliquer des contrôles structurants, comme le fait de limiter les écritures et de réduire les endroits où des scripts peuvent être déposés sans que vous les ayez déployés.
Une erreur courante est de vouloir autoriser “tous les fichiers PHP” dans wp-content, puis de dire que c’est une allowlist. Techniquement ça peut réduire certaines attaques, mais ça rend l’allowlist moins utile. L’objectif est https://gardewp.fr/securite-wordpress/ https://gardewp.fr/securite-wordpress/ d’oser une granularité: autoriser les chemins attendus, et refuser l’implicite.
Voici une approche pratique, que j’ai vue fonctionner sur des sites de taille variée, avec des trade-offs assumés.
Répertorier les dossiers qui doivent exister en permanence (themes, plugins, uploads, éventuellement un dossier de cache connu). Identifier les répertoires qui peuvent recevoir des créations en continu (uploads surtout, certains caches, parfois tmp). Définir les dossiers où l’écriture doit être quasi interdite hors déploiement (par exemple les dossiers qui ne devraient contenir que du code statique de thème ou plugin). Déterminer les URL ou scripts qui ne doivent jamais être exposés au public (selon votre configuration et vos plugins). Documenter les exceptions avec une justification courte (exemple: “cache généré par X, utile au rendu”, ou “endpoint d’API utilisé par Y”).
Cette étape peut sembler “bureaucratique”, mais elle évite le scénario classique : vous bloquez quelque chose, puis vous cherchez qui a besoin de cette exception, et pourquoi. Quand l’équipe est sollicitée en pleine nuit, les notes font gagner des heures.
Les décisions difficiles: où autoriser, où refuser
Une allowlist impose des choix. Le problème, c’est que certains choix sont visibles uniquement au moment où une attaque ou un incident se déclenche.
Par exemple, autoriser les uploads, oui. Mais faut-il autoriser l’exécution de PHP dans les uploads ? Très souvent, la réponse est non. WordPress n’a pas besoin que des uploads soient exécutables en PHP. Quand on voit un serveur où l’exécution est autorisée, c’est une opportunité pour des intrusions qui déposent un fichier malicieux.
Même chose pour les dumps, archives, fichiers temporaires. Si un plugin génère des exports dans un dossier spécifique, ce dossier doit être autorisé à être créé, mais l’exécution doit rester bloquée. Il faut donc faire la distinction entre création de fichiers et exécution de fichiers.
Autre dilemme: les scripts nécessaires au fonctionnement peuvent être générés ou modifiés par des plugins de sécurité eux-mêmes, ou par des plugins de performance (minification, bundling, préchargement de caches). Les allowlists trop strictes cassent le rendu ou le cache. L’astuce que j’utilise est de séparer les “zones statiques” et les “zones dynamiques”, puis de n’appliquer la restriction forte qu’aux zones statiques ou aux chemins sensibles.
Enfin, le cas des environnements multi-sites (WordPress Multisite) change la donne. La structure des dossiers peut différer, et des tenants du réseau peuvent produire des fichiers dans des emplacements supplémentaires. Une allowlist “mono site” appliquée telle quelle conduit à des blocages.
Exemples concrets d’incidents et comment l’allowlist change le résultat
Un scénario fréquent: une tentative d’exploitation vise wp-content en cherchant des points d’écriture, puis dépose un script qui exfiltre des données, souvent dans un répertoire qui “n’attire pas l’œil” ou avec un nom banal. Si votre allowlist refuse les écritures ou l’exécution dans les emplacements non attendus, le dépôt échoue, ou le script reste inactif.
Autre scénario: un attaquant ne dépose pas directement un webshell. Il modifie une configuration, puis détourne une fonction prévue pour charger des fichiers externes ou pour traiter des templates. Une allowlist d’URL ou de chemins peut rendre l’enchaînement moins trivial, surtout si certaines routes ne sont pas utilisées par votre site.
Il y a aussi les cas “propres”, mais problématiques: un site mal configuré autorise trop de types de fichiers en upload. Le jour où un contenu inattendu est accepté, l’attaquant peut s’appuyer sur un comportement du navigateur ou du serveur. Là, l’allowlist sur les types et les chemins d’uploads limite le risque, même si le vecteur initial n’est pas totalement neutralisé.
Je n’affirme pas que l’allowlist empêche 100% des attaques. Elle ne remplace pas la mise à jour, la gestion des droits, ni une bonne hygiène des identifiants. Mais elle rend les attaques “persistantes” plus difficiles à obtenir, parce qu’elles doivent d’abord respecter votre modèle de ce qui est autorisé.
Mise en œuvre, sans “bloquer pour bloquer”
La mise en place dépend de l’infrastructure. Certains hébergeurs proposent des outils qui gèrent des règles de type allowlist, d’autres laissent faire via Nginx, Apache, ou un WAF. Dans tous les cas, je conseille d’éviter le déploiement d’un changement majeur en production sans fenêtre d’observation.
La stratégie qui m’a le mieux réussi est progressive.
1) Tester sur un environnement de staging avec la même version de plugins et de thème. 2) Construire une version “mode observation”, si l’outil le permet, où vous loguez les blocages sans forcément casser. 3) Déployer ensuite une version fermée sur un périmètre réduit, puis étendre.
Le point clé est l’observabilité. Si vous ne pouvez pas voir ce que vos règles bloquent, vous allez corriger à l’aveugle. Sur un WordPress réel, les exceptions ont souvent une apparence banale, et vous ne la verrez qu’à la première requête d’un client ou d’un job programmé.
Voici un exemple d’exception justifiée que l’on rencontre parfois: un plugin d’optimisation d’images crée des fichiers dérivés à la volée, parfois dans un dossier spécifique. Si votre allowlist autorise uniquement les uploads “classiques”, vous allez obtenir des images qui ne se génèrent pas. La correction n’est pas de “tout ouvrir”, mais d’ajouter précisément le chemin et, idéalement, de conserver la règle “pas d’exécution”.
Relier allowlist et gestion des mises à jour
Une allowlist vit mal avec l’absence de maintenance. Ce n’est pas un problème de philosophie, c’est un problème de compatibilité.
Quand vous mettez à jour un plugin, trois choses peuvent changer: de nouveaux fichiers sont ajoutés, des endpoints deviennent disponibles, et le comportement de génération de fichiers peut évoluer. Si votre allowlist est trop stricte, chaque mise à jour devient une mini-urgence.
La gestion raisonnable consiste à intégrer l’allowlist dans votre processus de mise à jour.
Après une mise à jour, vous vérifiez rapidement que les chemins et comportements autorisés restent cohérents. Si votre site a des tests ou au moins un parcours utilisateur simple (connexion, publication, formulaire, chargement de pages typiques), c’est suffisant pour déceler la plupart des régressions. Vous cherchez aussi la création de nouveaux répertoires ou de nouveaux types de fichiers, ce qui peut justifier un ajustement de la liste.
Le piège, c’est de corriger l’allowlist en ajoutant tout ce que vous voyez sans comprendre. Sur le long terme, une allowlist “s’effrite”. Elle devient une liste qui ressemble davantage à une liste noire “qui a oublié ce qu’elle voulait bloquer”. Le remède est l’explication. Chaque ajustement doit avoir un contexte: quel plugin, quelle fonction, quel besoin.
Contrôles complémentaires qui rendent l’allowlist plus efficace
Une allowlist améliore la sécurité, mais elle fonctionne mieux quand elle s’additionne à d’autres protections “de base”.
D’abord, la gestion des rôles et des droits. Un attaquant qui arrive à obtenir un compte avec des droits élevés a déjà franchi une barrière majeure. L’allowlist limite la capacité à déposer et exécuter du code, mais si vous autorisez des actions qui permettent l’installation de plugins ou l’édition de fichiers depuis l’interface, vous augmentez la surface.
Ensuite, la rotation des identifiants et la limitation des tentatives de connexion. Les règles réseau peuvent réduire le bruit, mais l’audit doit aussi repérer les comptes orphelins, les utilisateurs créés sans raison, ou les comptes inactifs toujours actifs.
Enfin, la surveillance. Une allowlist ne doit pas être “définie une fois puis oubliée”. Les journaux doivent indiquer les tentatives bloquées, surtout quand elles répètent des schémas. Ce que vous cherchez, ce n’est pas seulement des alertes bruyantes, c’est la cohérence: un blocage répétitif sur un chemin précis peut signaler une tentative de persistance.
Je le dis souvent aux équipes qui découvrent ces mécanismes: la liste blanche est un garde-fou, mais c’est aussi un capteur. Elle vous apprend où vous êtes attaqués, et elle vous oblige à connaître votre propre site.
Un plan de travail sur 7 à 10 jours, réaliste pour une équipe
Sans imposer un calendrier universel, je vous donne une approche pragmatique, qui a l’avantage de produire des résultats sans tout révolutionner.
Jour 1 à 2: audit de l’état initial, inventaire des plugins et thèmes, relevé des chemins existants et cartographie des zones qui reçoivent des fichiers. Jour 3 à 4: construction d’une première version de l’allowlist sur un périmètre limité, et tests sur staging si disponible. Jour 5: intégration progressive en mode observation ou en blocage partiel, collecte des logs, identification des exceptions réelles. Jour 6 à 7: durcissement plus ferme sur les zones à risque, validation fonctionnelle (pages clés, formulaires, jobs prévus). Jour 8 à 10: itérations, documentation des règles, et mise en place d’un rythme de contrôle après mises à jour.
La réalité, c’est que la dernière semaine est souvent la plus utile, parce que vous corrigez moins et vous comprenez mieux. L’allowlist finit par devenir un outil de gouvernance, pas seulement un mécanisme technique.
Gérer les exceptions sans perdre le contrôle
C’est là que beaucoup d’allowlists échouent. On “ajoute juste un chemin” parce que le site cassait. Puis on ajoute encore. Puis on finit avec une liste si permissive qu’elle ne sert plus à grand-chose.
Je préfère un cadre simple pour les exceptions, avec une logique de durée.
Une exception peut être permanente si le besoin est stable et que le chemin est clairement limité. Elle peut être temporaire si un plugin doit être corrigé, remplacé, ou si vous avez besoin d’une correction d’hébergement. Elle doit surtout être vérifiable. Si vous ne savez plus à quoi correspond une exception dans six mois, vous n’avez pas une allowlist, vous avez un amas de permissions.
Dans un projet récent, on a gardé une exception liée à un cache généré. Au bout de deux mises à jour, le dossier changé a créé des blocages. L’équipe a d’abord “rouvert” plus large, puis s’est rendu compte que le plugin avait migré son comportement. La bonne correction a été de réviser l’allowlist avec un chemin plus strict et de supprimer l’ancienne exception. Le gain n’était pas uniquement sécuritaire, il était aussi opérationnel: moins d’incidents et moins de temps perdu.
Comment savoir si l’allowlist fonctionne
Vous aurez rarement une preuve spectaculaire du type “aucune attaque pendant 30 jours”. Ce n’est pas ainsi que la sécurité se mesure. On mesure plutôt des indicateurs.
D’abord, le taux de blocages sur des patterns connus. Si vos logs montrent des tentatives sur des chemins non autorisés, c’est un bon signe. Ensuite, la stabilité du site. Une allowlist qui casse souvent n’est pas une victoire, c’est une dette. Enfin, la capacité à diagnostiquer: quand un blocage se produit, est-ce que vous pouvez expliquer pourquoi, et comment ajuster sans ouvrir trop ?
Je recommande aussi de faire un contrôle régulier des fichiers. Une allowlist peut limiter les dépôts, mais un site compromis peut parfois modifier des éléments que vous aviez autorisés par erreur au départ. Là, l’audit reste indispensable, mais il devient plus ciblé.
Les limites, et ce que la liste blanche ne fera pas à votre place
Il faut être clair sur les limites.
Une allowlist n’empêche pas une compromission au sens large si un attaquant obtient un accès admin, modifie votre modèle de pages, ou exploite une vulnérabilité côté plugin. Elle réduit surtout la capacité à exploiter certains vecteurs qui dépendent d’emplacements ou de chemins non attendus.
Elle ne remplace pas non plus une bonne stratégie de sauvegarde. Une règle mal interprétée, un plugin mis à jour qui change un comportement, un serveur qui redémarre avec des paramètres différents, et votre site peut devenir instable. La sauvegarde vous donne le droit d’expérimenter avec un filet.
Enfin, l’allowlist est un effort. Si vous n’avez pas de temps pour l’entretenir, mieux vaut commencer plus petit, par exemple sur les chemins d’écriture et l’exécution dans les zones sensibles, plutôt que vouloir couvrir tout WordPress dès le premier jour.
Cas pratique: un périmètre d’abord, puis l’extension
Pour finir, je propose un exemple de démarche concrète sans entrer dans des détails dépendants de votre hébergeur.
Supposons que vous identifiez des risques liés à wp-content et aux uploads. Votre première allowlist se concentre sur deux choses: les chemins où un upload peut exister, et les chemins où l’exécution de PHP ne doit jamais être possible. Vous créez ensuite une règle de blocage sur les emplacements qui ne devraient pas recevoir du code déposé.
Une fois que le site fonctionne, vous ajoutez une couche sur les endpoints que vos plugins utilisent vraiment, et vous refusez les autres si c’est compatible. Ensuite seulement, vous vous attaquez aux comportements plus fins, comme certains patterns de requêtes ou des restrictions sur l’écriture.
Cette progression évite le piège du “tout, tout de suite”. Elle maintient la sécurité et la fiabilité ensemble, ce qui est le but.
Si vous deviez retenir une idée: une allowlist efficace est un document vivant. Elle naît d’un audit et sécurisation WordPress sérieux, puis elle s’affine avec des exceptions justifiées, des tests, et une surveillance utile.
Quand c’est bien fait, le résultat est net: moins de surfaces ouvertes par défaut, des blocages plus lisibles, et une meilleure capacité à réagir rapidement quand quelque chose dérive.