Sécuriser WordPress : audit des permissions sur /wp-content/
WordPress vous laisse faire beaucoup de choses facilement, y compris parfois des réglages qui rendent la sécurité plus fragile. Parmi les endroits les plus sensibles, il y a systématiquement le répertoire wp-content. C’est là que vivent vos thèmes, vos extensions, vos uploads, et souvent vos sauvegardes, caches, et fichiers générés par des plugins. Un mauvais réglage de droits ne “casse” pas forcément le site immédiatement, mais il peut faciliter une modification non autorisée, ou rendre plus simple l’escalade après une compromission.
Cet article détaille une démarche d’audit et de sécurisation WordPress centrée sur les permissions de /wp-content/. L’objectif n’est pas de viser un chiffre magique, mais de construire une politique de permissions cohérente avec votre architecture, vos déploiements, et le fonctionnement réel de votre serveur.
Pourquoi wp-content mérite un audit minutieux
Sur un site WordPress “standard”, la logique des permissions ressemble à ceci : votre serveur web (le plus souvent via www-data, apache, ou un autre utilisateur de service) doit pouvoir lire certains fichiers, et écrire dans des endroits précis (notamment uploads). Les thèmes et les extensions, eux, doivent surtout être lisibles. Quand l’écriture est trop large, vous créez une zone grise.
Je l’ai vu à plusieurs reprises sur des environnements hérités : tout était en 777 pendant une période de dépannage, puis personne n’a vraiment remis d’ordre. Le site fonctionnait, mais le risque ne se voyait pas. Le jour où un plugin a eu une vulnérabilité, le “simple” fait de pouvoir déposer ou modifier des fichiers dans wp-content a changé la gravité de l’incident.
Il y a un autre angle, plus opérationnel : certains plugins écrivent aussi dans des sous-dossiers de wp-content en dehors de uploads. Les builders de pages, certains systèmes de cache, les plugins de traduction, ou encore des connecteurs de médias peuvent créer des caches, des fichiers temporaires, ou des exports. Si vous réduisez trop les droits sans comprendre ces usages, vous obtiendrez des erreurs incompréhensibles côté administration, ou des téléchargements qui échouent.
Le bon audit sert donc deux objectifs : réduire la surface d’écriture non nécessaire, et maintenir la fonctionnalité.
Comprendre la logique Unix des permissions (sans se perdre)
Sous Linux, chaque fichier ou dossier porte trois permissions pour trois catégories :
le propriétaire (souvent l’utilisateur qui a déposé les fichiers), le groupe, les autres.
À cela s’ajoutent les bits “spéciaux” comme setuid, setgid, et “sticky” sur certains dossiers. Dans le cadre de WordPress, ce que vous voulez surtout éviter, ce sont les droits “écriture” trop ouverts, et les permissions trop permissives sur des emplacements non prévus pour recevoir des fichiers.
Pour donner un ordre de grandeur utile, je raisonne souvent comme suit :
Les fichiers de thèmes et d’extensions : généralement lisibles, pas modifiables par “tout le monde”. Les dossiers : lisibles et traversables, et parfois modifiables uniquement par le service web ou un processus d’administration. Les uploads : écriture nécessaire, mais idéalement en limitant le périmètre.
En pratique, les valeurs que vous verrez le plus souvent sont du style 755 pour des dossiers (lecture et exécution pour tous, écriture limitée), et 644 pour des fichiers. Pour uploads, beaucoup d’installations finissent par utiliser 755 ou 750 selon la politique de groupe, et parfois 775 pour faciliter l’écriture. Le détail dépend de l’utilisateur qui dépose vos médias et du groupe employé.
Le risque principal n’est pas le “chiffre exact”, c’est la combinaison “trop de monde peut écrire”.
Cartographier les usages : de qui vient l’écriture ?
Avant de modifier quoi que ce soit, j’aime répondre à une question très concrète : quel processus doit écrire dans wp-content ?
Sur un serveur classique, vous avez :
le serveur web, qui exécute PHP, éventuellement un déploiement par CI/CD, un outil de synchronisation, ou un utilisateur SSH, parfois des tâches planifiées (cron système, cron WordPress, ou un outil externe).
Si vos fichiers sont déposés par un compte SSH “admin” et que le serveur web exécute avec un utilisateur différent, vous allez souvent vouloir une stratégie de groupe pour éviter de donner l’écriture “aux autres”. Cela passe par des réglages du groupe et par des bits comme setgid sur les dossiers, plutôt que par des 777.
Un signe fréquent d’une politique bancale est l’existence d’un mélange de propriétaires : certains dossiers appartiennent à root, d’autres à www-data, d’autres à un utilisateur de déploiement. Ce mélange n’est pas forcément “mauvais” en soi, mais il rend l’audit plus difficile et augmente les chances d’un oubli.
Méthode d’audit : ce que vous vérifiez vraiment
L’audit commence par observer, pas par corriger. L’objectif est d’identifier :
- les endroits où l’écriture “trop large” existe, 2) les emplacements où l’écriture est nécessaire, 3) les incohérences de propriétaire et de groupe, 4) les cas limites liés aux sous-dossiers (comme cache, upgrade, languages, etc.).
Dans la plupart des cas, vous pouvez commencer par lister les droits récursivement. La commande exacte dépend de votre environnement, mais l’idée est la même : repérer les dossiers et fichiers avec des permissions qui sortent du cadre attendu.
Je me focalise particulièrement sur :
les sous-dossiers de wp-content qui reçoivent des contenus (uploads et, parfois, d’autres), les dossiers qui stockent des caches (certains sont recréés), les dossiers où des plugins écrivent des fichiers temporaires, les fichiers au-delà de la logique PHP (par exemple des .log, des .json, des .txt, ou des bundles).
Un point pratique : sur uploads, les droits peuvent être multiples selon les sous-dossiers (année/mois/selon réglage ou organisation). L’audit doit donc être tolérant aux variations, mais strict sur les permissions qui autorisent l’écriture par “les autres”.

Les signaux d’alerte les plus fréquents sur /wp-content/
Quand je fais un audit sur un parc, les problèmes reviennent avec une régularité presque rassurante. Le but n’est pas de paniquer, c’est d’identifier vite ce qui mérite d’être corrigé en priorité.
Voici les principaux signaux d’alerte que je cherche, dans cet ordre de gravité relative :
Des permissions “écriture pour tous” sur des répertoires ou fichiers non prévus pour recevoir des contenus. Des dossiers propriétaires “root” avec une écriture ouverte, ou au contraire des dossiers appartenant à un compte inattendu qui finit par forcer des contournements. Des incohérences de groupe entre les dossiers et les fichiers, qui conduisent à des échecs d’écriture et à des ajustements manuels. Des sous-dossiers de wp-content qui prennent l’habitude d’être modifiables sans raison (par exemple certains caches devenant persistants). La présence de fichiers modifiés très récemment qui ne devraient pas l’être, combinée à des droits permissifs.
Le piège, c’est de corriger “au feeling” sans corréler avec le fonctionnement du site. Un cache mis en place par plugin peut exiger l’écriture dans un sous-dossier précis, et si vous le rendez non modifiable, vous cassez la pagination, le minify, ou des exports.
Ajuster sans casser : stratégie de permissions réaliste
Il y a deux contraintes qui s’opposent souvent :
Sécurité : limiter les écritures. Maintenabilité : ne pas se retrouver à changer les permissions à la main à chaque déploiement ou mise à jour.
La stratégie que je trouve la plus robuste consiste à distinguer le type de contenu :

Fichiers PHP et ressources de thèmes/extensions : lecture seule pour le serveur web, écriture réservée aux processus de déploiement ou à l’administration. Dossiers d’uploads : écriture pour le serveur web, en limitant le périmètre via groupe. Dossiers de cache et générés : écriture possible uniquement si le plugin en dépend, et idéalement dans des emplacements connus.
Sur beaucoup de serveurs, une approche “droit par défaut” du type 755 pour les dossiers et 644 pour les fichiers est une base saine. Pour uploads, vous pouvez viser une base proche, mais en gardant une écriture nécessaire. Selon votre configuration, 775 ou 750 pour les dossiers d’uploads est souvent un compromis acceptable, à condition que le groupe soit correctement aligné.
L’autre levier, souvent sous-estimé, c’est le bit setgid sur les dossiers. Si vos dossiers d’uploads ont le bon groupe et que setgid est activé, les fichiers créés héritent du groupe. Cela réduit les cas où un sous-dossier finit avec un groupe différent, puis où l’écriture casse après une action.
Checklist terrain pour un audit et une sécurisation WordPress (sur /wp-content/)
Avant toute modification massive, je passe par une mini séquence de vérification. Elle tient en quelques minutes, mais évite des retours en arrière.
Vérifier l’utilisateur du serveur web (sur le serveur, pas depuis WordPress) et le groupe associé au runtime PHP. Repérer les sous-dossiers de wp-content réellement écrits : uploads en priorité, puis ceux qui sont utilisés par vos plugins (cache, logs, etc.). Contrôler l’existence de permissions trop ouvertes sur wp-content (écriture pour “other” surtout). Tester un scénario fonctionnel après correction : upload d’un fichier, mise à jour d’un plugin si possible, régénération de cache si activé. Documenter vos choix (utilisateur, groupe, et règle d’héritage) pour que le prochain déploiement ne “remette pas tout à zéro”.
Cette checklist est volontairement simple, parce qu’on gagne rarement en sécurité en multipliant les hypothèses. On gagne en fixant un cadre et en le vérifiant.
Cas pratiques : trois scénarios typiques
1) Le site fonctionne, mais wp-content est trop permissif
C’est le scénario le plus fréquent sur des migrations. Vous trouvez des dossiers avec des droits très ouverts, parfois 777 sur certains sous-dossiers oubliés. Le site “marche”, alors personne ne touche.
La correction efficace consiste généralement à revenir à un standard plus strict, tout en gardant l’écriture nécessaire sur uploads et sur les dossiers explicitement utilisés par des plugins. La clé est de corriger en tenant compte des propriétaires et du groupe, sinon vous créez de nouveaux échecs.
2) Les uploads échouent après “durcissement”
Autre scénario classique : quelqu’un a appliqué une règle globale sur wp-content avec une écriture limitée, puis WordPress renvoie des erreurs d’upload ou des “images non importées”. Le symptôme peut sembler vague, mais la cause est souvent la même : le serveur web n’a plus le droit d’écrire au bon endroit, ou bien l’héritage de groupe ne fonctionne plus.
Ici, je préfère corriger la politique de groupe plutôt que de ré-élargir l’écriture à tout le monde. Si vos fichiers sont déposés par un processus différent, un ajustement de groupe et de setgid rend l’ensemble stable.
3) Un plugin écrit dans un sous-dossier inattendu
Il existe des plugins qui stockent des fichiers générés dans des zones “non intuitives” de wp-content. Cela arrive avec des outils de traduction qui créent des bundles, des systèmes de sécurité qui enregistrent des fichiers temporaires, ou des solutions de cache qui gardent une structure de répertoires persistante.
Dans ce cas, la correction n’est pas seulement de “mettre uploads en écriture”. Il faut identifier le dossier exact utilisé et appliquer une règle spécifique. On obtient alors un durcissement global sans casser le plugin.
Les détails qui font la différence : propriétaire, groupe, et héritage
Beaucoup d’articles parlent uniquement des permissions numériques. En audit terrain, le triptyque propriétaire - groupe - héritage est souvent plus déterminant.
Si vos fichiers sont détenus par un utilisateur différent de celui du runtime PHP, et que vous ne jouez GardeWP sécurité plugins WordPress pas sur le groupe, vous devrez soit élargir les droits, soit multiplier les ajustements manuels. C’est ce qui fait dériver les systèmes vers des configurations dangereuses.
Je recommande une cohérence “par défaut” : un groupe pour les fichiers servis et un autre pour les opérations d’écriture si besoin. Ensuite, vous alignez le serveur web et le processus de dépôt sur ce groupe.
Le bit setgid sur les dossiers d’uploads et, si nécessaire, sur quelques dossiers générés, garantit que le groupe reste stable quand des fichiers sont créés. Cela réduit le nombre de cas où des sous-dossiers finissent avec une propriété incohérente.
Comment corriger : approche progressive plutôt que globale
La tentation est grande de lancer une correction récursive uniforme. Sur un parc, j’ai appris que c’est rarement la meilleure approche, parce que WordPress et ses plugins produisent des fichiers à la volée, avec des profils d’accès différents.
Une approche progressive ressemble à ceci en logique :
corriger d’abord ce qui est clairement non nécessaire (écriture trop ouverte sur des fichiers et dossiers qui ne doivent pas bouger), puis traiter séparément uploads, enfin, ajuster les exceptions de plugins en ciblant les sous-dossiers concernés.
Cela demande de prendre le temps de comprendre ce que vous avez. En échange, vous limitez les régressions et vous réduisez le risque de casser des fonctionnalités “rares mais importantes”, comme l’export d’un média, la génération d’un PDF, ou l’import d’un fichier dans un module spécifique.
Intégrer l’audit dans votre processus de déploiement
L’audit ne doit pas être une photo à un instant donné. Sinon, au premier déploiement, les permissions reviennent dans l’état précédent. Dans des environnements avec CI/CD ou synchronisation (rsync, Git-based deploy, conteneurs), il faut verrouiller une règle.
Ce que je vise est simple : à chaque déploiement, vous contrôlez les permissions sur les fichiers versionnés, et vous laissez le mécanisme d’écriture dynamique fonctionner uniquement sur les répertoires prévus.
Il est aussi utile de définir une routine de contrôle à faible coût, par exemple vérifier périodiquement l’apparition de permissions trop ouvertes dans wp-content. Une détection précoce évite la dérive lente vers des configurations dangereuses.
Les limites à connaître, pour éviter de sursécuriser
Serrer trop fort peut produire des dégâts. Si des plugins dépendent d’écriture dans des dossiers de cache ou de génération, vous risquez des erreurs silencieuses. Parfois, ce ne sera visible qu’après une heure, ou lors du prochain pic de trafic quand un cache doit se régénérer.
Il y a aussi des cas où un plugin utilise des permissions spécifiques pour des raisons techniques. Vous ne voulez pas “tout uniformiser” sans comprendre. Le bon jugement consiste à vérifier, puis à corriger avec ciblage.

Enfin, gardez en tête que les permissions ne remplacent pas d’autres mesures. Même une politique parfaite sur /wp-content/ ne compense pas un thème vulnérable, des plugins non mis à jour, ou une configuration PHP faible. L’audit s’inscrit dans une démarche d’audit et de sécurisation WordPress plus globale.
Une mini liste d’actions à haut impact (sans bruit inutile)
Si vous ne deviez faire que quelques choses dès maintenant, je prioriserais celles qui réduisent le risque rapidement, tout en gardant le site fonctionnel. Voici les actions les plus “rentables” que j’ai vues en pratique, avec un esprit de prudence :
Réduire l’écriture “pour les autres” sur l’essentiel de wp-content, et limiter strictement les exceptions. Aligner propriétaire et groupe sur les dossiers que le serveur web doit écrire, plutôt que d’ouvrir au maximum. Appliquer une logique d’héritage (par groupe, éventuellement via setgid) sur les dossiers recevant des créations. Cibler les exceptions des plugins, plutôt que d’appliquer une règle globale à tout wp-content.
Ce que vous devriez constater après correction
Quand la politique de permissions est cohérente, vous voyez des résultats concrets :
uploads fonctionnent, y compris après une série de tests (multimédias, import, régénération), l’interface WordPress ne renvoie pas d’erreurs de droits, les mises à jour de plugins ne déclenchent pas de cascades de permissions incohérentes, le nombre de “dossiers bizarres” (propriétaires mélangés, droits trop ouverts) diminue.
Le site garde son ergonomie, mais votre surface d’attaque diminue. Dans la vraie vie, cette différence est particulièrement visible quand vous enchaînez un incident ou une suspicion de compromission : vous pouvez limiter la capacité de modification, et donc ralentir le “travail” d’un attaquant.
Dernier point : ne confondez pas audit et preuve
Un audit réussi, ce n’est pas seulement “je vois des droits corrects”. C’est aussi “je suis capable d’expliquer pourquoi ces droits sont corrects pour mon usage”.
Documentez au moins ceci : le rôle du serveur web, la stratégie de groupe pour wp-content/uploads, et les exceptions de plugins que vous avez identifiées. Si demain quelqu’un change d’outil de déploiement, vous saurez quoi vérifier, et vous éviterez la régression.
Sécuriser WordPress passe souvent par des gestes répétitifs, mais ceux sur les permissions sont parmi les plus sensibles et les plus gratifiants. Quand wp-content redevient un espace contrôlé, vous réduisez une voie d’attaque qui, autrement, reste discrètement ouverte pendant des mois.