Hardening WordPress : réduire la surface d’attaque avec les permissions minimales
Quand on parle de hardening WordPress, on pense souvent à la sécurité applicative, aux mises à jour, aux plugins “anti-quelque chose”. Pourtant, une bonne partie des incidents naissent d’un problème plus silencieux: trop de droits, trop largement distribués. Un fichier accessible en écriture quand il ne devrait pas l’être, un compte système trop puissant, un utilisateur WordPress autorisé à faire des choses qu’il n’utilise jamais.
Réduire la surface d’attaque avec les permissions minimales, ce n’est pas une lubie d’administrateur pointilleux. C’est une façon de rendre l’impact de tout compromis plus faible. Si un attaquant réussit à injecter du contenu via un plugin vulnérable, son rayon d’action dépend fortement de ce que le serveur et l’application laissent faire. Et ça, on peut le travailler, de manière concrète.
La logique “moins de droits” appliquée à WordPress
WordPress est un système qui combine plusieurs couches: le système de fichiers, le processus web (souvent via PHP-FPM ou mod_php), la base de données, l’application PHP, puis le modèle de rôles côté interface. Une permission trop permissive à n’importe quel étage peut annuler le bon travail fait ailleurs.
Le principe général est simple: donner uniquement ce qui est nécessaire, au moment nécessaire, et le retirer le reste du temps. Dans la pratique, cela se décline en trois axes.
D’abord, les permissions système: qui possède quels fichiers, et qui peut écrire où. Ensuite, les permissions d’accès à la base: quel utilisateur MySQL ou MariaDB peut lire et écrire, et sur quelles tables. Enfin, les permissions fonctionnelles dans WordPress: qui peut publier, installer, modifier des thèmes, accéder à des réglages sensibles.
Le point clé est le suivant: une politique “tout en admin” ou “tout en writable” ne se voit pas à l’œil nu. Elle se traduit en incidents, souvent après coup. J’ai déjà vu un site où les droits de dossiers uploads étaient trop larges. Un plugin compromis a pu déposer des charges dans un endroit écrivable sans déclencher d’alerte, parce que l’environnement autorisait déjà l’écriture. Le correctif a été autant une opération de droits qu’un patch logiciel.
Démarrer par les droits de fichiers: ce qui compte vraiment
Les permissions POSIX (les fameux chmod) et la propriété des fichiers sur le serveur sont le socle. L’objectif n’est pas de “mettre des chiffres au hasard”, mais de garantir que:
1) le webserver peut lire ce qui doit l’être,
2) il peut écrire uniquement là où WordPress doit créer ou modifier des éléments (généralement wp-content/uploads), 3) le reste est protégé contre l’écriture depuis le contexte d’exécution PHP.
Dans un scénario classique, vous avez un utilisateur système (par exemple www-data, nginx, apache, ou un user dédié PHP-FPM) qui exécute le code PHP. Le répertoire WordPress doit être majoritairement en lecture seule pour ce compte. Les dossiers qui doivent recevoir des uploads (souvent wp-content/uploads et ses sous-dossiers) peuvent être en écriture. Les fichiers comme wp-config.php doivent rester inaccessibles en écriture.
Sur beaucoup d’hébergements “corrects” par défaut, les permissions ressemblent à ceci en pratique (les valeurs exactes varient selon l’environnement, mais la logique reste la même):
fichiers PHP: lisibles par le webserver, pas forcément exécutables dans le sens POSIX, mais lisibles et traités par PHP; répertoires WordPress: lisibles, traversables, pas écrits par le webserver; wp-content/uploads: lisible et écrivable pour permettre l’upload d’images et la création des fichiers.
Un piège fréquent: donner des droits trop larges pour “que l’upload marche”, puis oublier que ces mêmes droits peuvent servir à autre chose si l’application est compromise. Un exemple concret: si wp-content (ou pire, tout wp-content) devient inscriptible, une charge déposée via un point d’entrée applicatif a plus de latitude pour persister.
Propriété et groupe: le duo souvent mal compris
Les permissions ne sont pas uniquement une histoire de “chmod”. La propriété (user owner) et le groupe (group) comptent tout autant. Si le webserver et certains scripts d’automatisation partagent un groupe commun, on peut obtenir un modèle plus propre que “monte à 777”.
Je préfère, quand c’est possible, une approche avec un user webserver stable et un groupe contrôlé, où l’écriture est confinée. Cela réduit le risque qu’un autre processus du même serveur écrase des fichiers sensibles.
wp-config.php: le petit fichier, gros enjeu
Wp-config.php contient les identifiants de base, parfois des clés secrètes, parfois des paramètres de sécurité. Il ne doit pas être lisible ou modifiable par des comptes non nécessaires. Sur un système où le webserver exécute le code, ce fichier doit être lisible par PHP (sinon WordPress ne démarre pas), mais pas en écriture.
La difficulté est que certains hébergeurs utilisent des modèles différents. Là où vous voyez “ça marche”, vous pouvez avoir des droits déjà faibles, mais trop “fonctionnels” côté hébergement. En durcissement, l’enjeu est de vérifier, pas de supposer.
Base de données: limiter ce que WordPress peut faire
Quand un attaquant obtient un accès applicatif (via une vulnérabilité ou un vol de session), il essaie ensuite de monnayer cette capacité. Si l’utilisateur base de données utilisé par WordPress est trop puissant, l’étape suivante peut devenir dramatique.
Dans WordPress, la base de données est gérée avec des identifiants définis dans wp-config.php. L’idéal est que l’utilisateur de base n’ait que ce qui est nécessaire:
lire et écrire sur les tables nécessaires au fonctionnement de WordPress; éventuellement exécuter des opérations requises par certaines fonctionnalités (création de tables lors de l’installation, mise à jour de schéma, indexation, etc.).
Dans les faits, beaucoup d’installations utilisent un compte très permissif, parfois avec des droits “large” sur l’ensemble du schéma, parce que c’est plus simple à l’installation. Une politique de permissions minimales, c’est l’idée de réduire ce champ.
Attention aux trade-offs: certaines mises à jour, certains plugins ou des opérations d’administration peuvent nécessiter des privilèges additionnels. Le durcissement ne doit pas transformer la maintenance en enfer. C’est pour ça que je recommande d’aborder la réduction de droits par itérations: réduire, tester les mises à jour, puis consolider.
WordPress: le vrai point d’attaque, ce sont les rôles
Les permissions minimales côté application ne se résument pas à “éviter admin”. Le problème vient aussi de l’accumulation: des comptes créés pour dépanner, des rôles trop élevés attribués par confort, des utilisateurs qui ne devraient jamais accéder aux réglages.
WordPress propose des rôles et des capacités. En durcissement, l’objectif est d’avoir le moins d’utilisateurs possible, chacun avec le rôle strictement nécessaire, et de retirer les droits non utilisés.
J’ai déjà vu une équipe marketing avec plusieurs comptes “éditeur”, mais aussi un compte “admin” partagé entre deux personnes. Même si chacun “s’en sert rarement”, un compromis de mot de passe ou de session sur ce compte donne accès à l’installation de plugins, aux modifications de thèmes, aux réglages avancés. En pratique, la réduction de surface d’attaque, c’est aussi la réduction du nombre de secrets et du partage.
Voici un ordre de priorité simple pour l’audit des comptes et rôles:
identifier les comptes ayant des capacités administratives (installation de plugins, gestion des thèmes, réglages système); réduire chaque compte au rôle nécessaire au quotidien (un éditeur n’a pas besoin d’installer quoi que ce soit); supprimer ou désactiver les comptes inactifs, surtout ceux avec des rôles élevés; séparer les comptes “technique” et “rédaction”, pour éviter qu’un besoin de publication soit lié à un risque d’administration.
Ce sont des actions modestes, mais elles changent beaucoup le niveau de dommage potentiel.
Mettre des garde-fous sur l’écriture: uploads, thèmes, plugins
Sur beaucoup de sites, le chemin d’attaque passe par un endroit où l’écriture est possible. WordPress a besoin d’écrire dans certains répertoires, mais pas partout.
uploads: utile, mais à surveiller
Le répertoire wp-content/uploads sert aux médias. C’est généralement le seul endroit où une écriture côté webserver est acceptable. Une mesure de hardening efficace consiste à limiter au maximum la possibilité de déposer des fichiers non attendus.
Selon votre stack, cela peut inclure des contrôles de type, d’extension, et des validations côté PHP, mais aussi des règles au niveau serveur. L’objectif n’est pas de “bloquer tout” (sinon l’upload devient injouable), mais de réduire les chemins réalistes.
Dans des environnements bien tenus, on évite aussi que des répertoires additionnels deviennent inscriptibles sans raison. Par exemple, rendre wp-content/plugins en écriture pour “résoudre une erreur de mise à jour” est une mauvaise idée: cela donne une porte ouverte à la persistance si un plugin est compromis.
themes et plugins: garder le contrôle du déploiement
Un modèle propre consiste à gérer les plugins et thèmes depuis un Site utile https://gardewp.fr/securite-wordpress/ processus maîtrisé (CI/CD, déploiement contrôlé, ou au minimum une session d’administration dédiée). Si la maintenance se fait depuis l’interface WordPress, cela reste possible, mais il faut compenser avec une politique de permissions stricte sur les comptes.
Le durcissement par permissions minimales ne dit pas “ne jamais installer depuis WordPress”. Il dit “ne donner à personne le droit d’installer sauf ceux qui en ont besoin, et limiter les droits au reste”.
REST API, AJAX et accès admin: réduire ce qui est exposé
WordPress expose des endpoints côté application, notamment via la REST API et des routes d’administration utilisées par certaines fonctionnalités. Là encore, la surface d’attaque dépend de la configuration et des permissions.
Le raisonnement “permissions minimales” s’applique à deux niveaux:
réduire le nombre de comptes capables d’accéder aux fonctions sensibles; réduire le nombre d’expositions inutiles (par exemple, des endpoints inutilisés, ou des fonctionnalités activées sans besoin).
Je ne recommande pas un “tout désactiver” systématique. Des plugins ou des intégrations peuvent dépendre de certaines routes. Le bon compromis est de vérifier ce que vous utilisez réellement.
Dans un audit que j’ai mené, la REST API était activée et utilisée pour un tableau de bord front. En coupant aveuglément, le front s’est cassé, et on a perdu du temps. La leçon: durcir sans casser, passe par l’inventaire des usages.
Permission minimale n’est pas seulement technique, c’est aussi opérationnel
Une partie du problème vient des habitudes d’exploitation. Si votre équipe règle les problèmes de permissions en “ouvrant large”, vous perdez progressivement le contrôle.
Par exemple, on voit parfois des démarches du type: “WordPress n’écrit pas, mettons wp-content en 777”. Ça règle l’incident sur le moment, mais ça crée un régime permanent dangereux. Le durcissement consiste à remplacer ces réflexes par une méthode d’investigation: vérifier l’utilisateur système PHP-FPM, vérifier la propriété des répertoires, vérifier le chemin exact d’écriture demandé par WordPress, puis corriger au plus juste.
Il y a aussi la question du modèle de déploiement. Si votre serveur est manipulé à la main en production, avec des droits élevés, le risque augmente. Si au contraire le déploiement s’appuie sur un processus versionné, les permissions peuvent rester cohérentes et contrôlées.
Une méthode pratique pour avancer sans tout casser
Je recommande de procéder en commençant par ce qui a le meilleur rapport bénéfice/risque: les points où l’écriture est trop large ou les droits trop étendus, et où on peut tester sans impact majeur.
Voici un chemin de travail, simple mais rigoureux:
relever l’état actuel des propriétaires et permissions sur wp-content/uploads et les répertoires parents, puis sur wp-config.php; vérifier les droits de l’utilisateur de base de données utilisé par WordPress, et limiter si possible à l’ensemble minimal requis; auditer les comptes WordPress, réduire les rôles, et désactiver ou supprimer les comptes inactifs; effectuer une passe de tests (médias, thèmes, mises à jour) avant et après changement, en suivant une fenêtre courte; documenter les écarts et garder un retour arrière prévu, si un plugin dépend d’un droit trop permissif.
C’est le genre de démarche qui évite les corrections “magiques” et maintient la sécurité dans le temps.
Edge cases: ce qui casse le “minimum” trop strict
Le durcissement sérieux rencontre toujours des exceptions. Elles ne sont pas un échec, elles signalent que WordPress ou des plugins ont des besoins spécifiques.
Quelques cas qu’on rencontre souvent:
certains plugins de cache ou de performance écrivent dans des répertoires supplémentaires; certains outils d’optimisation d’images peuvent créer des sous-dossiers particuliers ou utiliser des formats spécifiques; des systèmes de déploiement peuvent nécessiter un droit d’écriture ponctuel pour mettre à jour thèmes et plugins.
Le piège est de confondre “confinement” et “blocage total”. On peut conserver un modèle sûr en identifiant les chemins d’écriture nécessaires, puis en assurant que seuls les bons répertoires reçoivent les droits.
Autre point délicat: la compatibilité entre permissions et mécanismes d’hébergement. Sur des environnements gérés (surtout chez des hébergeurs à multi-tenant), les attentes peuvent être différentes, et la manière exacte de corriger une permission peut varier. Le principe reste, mais la recette change.
Vérifier après coup: comment savoir si c’est vraiment durci
Changer des permissions sans mesurer, c’est risqué. On veut être certain que le durcissement réduit le risque, sans bloquer l’application.
Côté application, vérifiez que:
l’upload fonctionne correctement pour les types attendus; WordPress peut créer les sous-dossiers nécessaires; les mises à jour que vous utilisez (celles que vous faites réellement) ne déclenchent pas d’erreurs “permission”.
Côté serveur, observez aussi les logs. Les erreurs liées aux permissions ont souvent une signature: “permission denied”, “failed to open stream”, “unable to create directory”. Ce sont des indices directs, pas des suppositions.
Si vous faites le changement en production, gardez une fenêtre d’observation courte, puis un retour rapide possible. Le but n’est pas de “faire un grand soir” de sécurité. Le but est d’installer une politique durable.
Les gains réels: pourquoi réduire les permissions change la donne
Le bénéfice principal, c’est la limitation de l’impact. Une attaque qui exploite une faille ne se transforme pas automatiquement en compromission totale. Si l’attaquant ne peut pas écrire là où il faudrait, s’il ne peut pas manipuler des fichiers sensibles, s’il ne peut pas obtenir de nouveaux privilèges via la base de données, la persistance et l’exfiltration sont plus difficiles.
Réduire les permissions minimales améliore aussi la capacité de détection et de réponse. Quand l’environnement est trop permissif, les événements se ressemblent, tout semble “possible”. Quand l’écriture et les droits sont confinés, les écarts deviennent plus visibles.
Et il y a un dernier avantage, souvent sous-estimé: la maintenance devient plus prévisible. Moins de “corrections de dernière minute” faites à la main avec des droits trop larges, moins de surprises lors d’un patch, moins de temps perdu à diagnostiquer des erreurs floues.
Si vous devez retenir une idée: le durcissement n’est pas seulement un ensemble de mesures, c’est un style de gestion des accès. En hardening WordPress, ce style commence par les permissions. Ensuite seulement, il devient plus facile de sécuriser le reste.
Si vous le souhaitez, je peux aussi proposer une grille d’audit adaptée à votre configuration (type d’hébergement, PHP-FPM ou Apache, architecture de base, présence de plugins courants), afin de traduire ces principes en décisions concrètes sans supposer ce que vous utilisez.