Contrainte de fichiers et permissions : optimiser la sécurité d’un site pro

Quand on parle sécurité d’un site WordPress, on pense vite au pare-feu, au durcissement de l’accès, aux mots de passe et aux plugins. Pourtant, une grosse partie des incidents “simples” naissent d’un sujet moins glamour, mais redoutable : la manière dont les fichiers sont stockés, accessibles et modifiés. La contrainte de fichiers et la gestion des permissions, ce n’est pas une formalité. Sur un site pro, c’est une barrière concrète contre l’écriture indésirable, l’escalade de privilèges et les dérapages pendant une maintenance.

J’ai vu des sites où le thème était “propre”, les mises à jour faites, et malgré ça une compromission finissait par transformer des pages publiques en portes d’entrée. La cause n’était pas un exploit compliqué, mais des droits trop larges, un dossier writable utilisé “par commodité”, ou un FTP encore accessible avec des permissions qui permettent d’écraser des fichiers sensibles. À l’inverse, quand les permissions sont correctement bornées, les erreurs et les tentatives deviennent beaucoup moins utiles, même si une autre couche de sécurité a du retard.

Le vrai problème derrière les permissions “trop larges”

Sur un serveur, un fichier n’est pas “safe” parce qu’il est WordPress. Il est safe parce que le serveur décide qui peut le lire, l’écrire et l’exécuter. Les permissions, c’est l’accord de distribution de la capacité à modifier le contenu.

Dans un contexte WordPress, cette capacité a une double face. D’un côté, WordPress a besoin d’écrire quelque part : uploads, caches, fichiers temporaires, parfois les mises à jour automatiques. D’un autre côté, écrire dans les mauvaises zones, ou donner l’écriture à plus large que nécessaire, revient à installer une trappe dans votre propre site.

Les risques typiques quand c’est mal réglé :

    Des fichiers systèmes modifiables par un processus web alors qu’ils ne devraient jamais l’être. Un répertoire “writable” qui devient une zone d’atterrissage pour du contenu malveillant. Des web shells ou des scripts qui ne devraient jamais être exécutables, mais qui le deviennent parce que l’exécution est autorisée dans un dossier non prévu.

Et il y a un détail que beaucoup sous-estiment : ce n’est pas seulement le réglage initial. Les permissions dérivent au fil du temps, après un transfert via FTP, une opération manuelle, une restauration de sauvegarde, ou un changement d’utilisateur sur le serveur.

Si votre objectif est une sécurité site WordPress professionnel, vous devez donc traiter les permissions comme un système vivant, pas comme une case à cocher une fois.

Comprendre ce que WordPress doit vraiment écrire

Avant de “verrouiller”, il faut savoir ce qui doit rester modifiable. WordPress n’exécute pas toute sa vie de la même façon. La plupart du temps, il lit. L’écriture est concentrée sur quelques répertoires et quelques moments.

Dans les installations standard, l’activité d’écriture concerne surtout :

    le dossier wp-content/uploads/ (contenu utilisateur, images), wp-content/cache/ ou d’autres répertoires de cache selon les plugins, parfois wp-content/plugins/ et wp-content/themes/ pendant des mises à jour, le stockage temporaire lié à l’installation, selon la méthode utilisée.

Le piège, c’est de se dire “puisque ça marche, on garde”. En pratique, on finit souvent avec des permissions globales généreuses sur wp-content, ou pire sur la racine WordPress. Le site continue de fonctionner, donc personne ne touche. Jusqu’au jour où un plugin défaillant, une mauvaise routine de maintenance, ou une compromission partielle trouve un espace où écrire.

Permissions et modes : le triangle qui compte vraiment

Sur Linux, on raisonne souvent en “chiffres” (mode octal) ou en “u/g/o” (user/group/other). Peu importe l’interface, le principe reste : vous définissez l’ensemble des actions autorisées.

Sur un site web, la règle pratique que je garde en tête est celle-ci : le processus web doit pouvoir lire et servir. Pour l’écriture, il faut viser le strict nécessaire, et limiter l’exécution là où elle n’a pas sa place.

Deux erreurs fréquentes :

1) Donner l’écriture à tout le monde (y compris “other”), en pensant que “c’est plus facile”. 2) Activer l’exécution dans des répertoires où seuls des fichiers statiques (ou du contenu téléchargé) devraient exister.

Selon l’hébergement, l’interprétation de l’exécution peut être influencée par la configuration du serveur (Apache, Nginx, PHP-FPM) et par le document root. Mais votre meilleure défense reste la cohérence : si un fichier ne devrait pas être exécutable, évitez de le rendre exécutable par des permissions trop souples.

Le cas pratique qui revient le plus : uploads et dérives

Le dossier uploads est souvent l’endroit où on tolère le write. Pourtant, c’est aussi l’endroit où des intrus aiment déposer des fichiers. La question devient alors : qu’est-ce qui est “déposé”, et est-ce que ce dépôt peut être “exécuté” ?

image

Même quand les permissions sont correctes, il faut garder un œil sur la configuration serveur. Par exemple, si PHP est interprété dans un dossier censé contenir uniquement des images, une méthode d’attaque peut viser à déposer un script dans ce périmètre.

Sur WordPress, les garde-fous existent souvent côté logique applicative, mais ils ne remplacent pas la discipline d’accès au système. Si vos permissions laissent “trop” d’espace en écriture et que la configuration serveur ne bloque pas l’exécution dans les bons endroits, vous créez un scénario qui ne pardonne pas.

Ce que je recommande dans une approche pragmatique : considérer uploads comme un espace où l’on peut ajouter, mais où l’on doit éviter les modes qui rendent l’exécution possible. Le bon réglage dépend de la stack, mais l’idée reste constante : autoriser l’écriture nécessaire, sans ouvrir une porte à l’exécution.

Les permissions pendant les mises à jour : le moment le plus fragile

Les mises à jour WordPress, plugin et thème ne sont pas juste “des clics”. Elles impliquent des écritures depuis PHP, parfois avec des mécanismes temporaires.

Le moment précis où l’on change des droits est délicat. J’ai déjà vu des équipes appliquer un durcissement le lundi, puis restaurer une sauvegarde le mardi, et re-découvrir un problème le mercredi. Le durcissement était bon, mais la restauration a remis des permissions différentes. Résultat : WordPress n’arrivait plus à écrire là où il devait, ou au contraire il écrivait plus largement qu’avant.

Il faut donc penser à deux familles de scénarios :

    “Je rends le système plus strict”. Très bien, mais je dois vérifier que WordPress peut encore gérer ses écritures légitimes. “Je dois rester strict malgré les opérations de maintenance”. Donc je dois répéter la vérification après une restauration, un déploiement, un changement de version ou un transfert de fichiers.

C’est aussi là que la discipline de déploiement compte. Si vous poussez votre code via Git vers un répertoire d’app, ou via un mécanisme CI, vous pouvez imposer un état de permissions contrôlé. Si vous utilisez encore des méthodes manuelles, surtout avec FTP, vous multipliez les variations de droits.

Utilisateur propriétaire, groupe, et cohérence : la petite différence qui évite les gros soucis

Beaucoup de problèmes viennent d’une incohérence entre l’utilisateur propriétaire des fichiers et l’utilisateur sous lequel tourne le serveur web (ou PHP-FPM).

En clair : si vos fichiers appartiennent à un utilisateur, mais que votre PHP s’exécute sous un autre, les droits peuvent devenir impossibles à gérer proprement. Alors, au lieu de corriger la cause, on augmente les droits pour “rendre ça possible”. C’est exactement la porte qui finit par servir à autre chose qu’à l’installation.

Une stratégie robuste consiste à choisir une logique de propriété claire, et à la maintenir :

    vous gardez un utilisateur de déploiement pour écrire sur le code, vous gardez un utilisateur web pour servir, et vous autorisez l’écriture seulement aux endroits nécessaires, selon le modèle prévu par votre hébergement.

Dans un site professionnel, c’est encore plus important si plusieurs personnes interviennent, ou si des outils de sauvegarde/restauration restaurent parfois avec des propriétaires différents.

Vérifier et corriger sans casser

On lit parfois des tutos qui disent “mets 755 partout” ou “mets 777 sur wp-content”. Ce genre de conseil n’a qu’un seul avantage : ça évite les erreurs immédiates. Mais il détruit aussi votre barrière de sécurité. Un site qui fonctionne avec 777 est un site qui donne à un attaquant une action très claire en cas de faille applicative.

L’approche correcte, surtout sur des environnements WordPress pro, ressemble plutôt à un diagnostic suivi d’un ajustement ciblé. Avant de modifier quoi que ce soit, je préfère cartographier :

    quels dossiers doivent être écrits par PHP, quels fichiers sont statiques et ne doivent jamais être exécutés, quels propriétaires et groupes existent réellement, et ce qui change après une opération (upload, mise à jour, restauration).

Voici un point de départ que j’utilise comme “contrôle qualité” avant d’appliquer un durcissement :

    Vérifier la cohérence du propriétaire et du groupe sur l’arborescence (racine, wp-content, uploads). Confirmer que seuls les répertoires nécessaires sont en écriture côté processus web. S’assurer que les fichiers PHP sont dans les emplacements prévus, pas dans des zones d’uploads “libres”. Tester les mises à jour depuis l’interface WordPress sur un staging, pas sur la prod la première fois. Refaire un contrôle après toute restauration ou déploiement, car les permissions reviennent parfois à l’état précédent.

Cette discipline évite la mauvaise surprise où le site “marche” mais devient excessivement permissif.

Une méthode simple pour raisonner sur “fichiers” vs “répertoires”

Sans rentrer dans un cours d’administration, une règle intuitive aide beaucoup : les répertoires sont là pour contenir, les fichiers sont là pour être servis ou exécutés.

    Les répertoires doivent permettre la création de contenus uniquement là où c’est nécessaire. Les fichiers doivent être lisibles par le serveur. Les fichiers PHP, eux, doivent rester exécutables seulement là où ils sont prévus et protégés par votre configuration.

Ce n’est pas seulement une question de mode. C’est aussi une question d’environnement, de configuration serveur, et de comportement des plugins. Par exemple, un plugin de cache peut créer des fichiers dans un répertoire. Un plugin de sauvegarde peut écrire temporairement. Un outil de déploiement peut changer les propriétaires. Si vous mettez tout en “large”, vous ne saurez plus ce qui a bougé.

Les bons durcissements, ceux qui tiennent dans la durée

Le durcissement utile, celui qui reste utile six mois après, n’est pas forcément le plus strict au sens mathématique. C’est celui qui survit à votre réalité opérationnelle.

Sur un site pro, vous avez généralement des contraintes : intégration continue, déploiements fréquents, interventions manuelles ponctuelles, demandes client sur l’installation de plugins, migrations. Le durcissement doit être “tenable”, sinon il sera contourné.

On obtient souvent un bon compromis en appliquant une politique qui distingue clairement :

    code applicatif (thèmes, plugins, cœur WordPress), données utilisateurs (uploads), caches et fichiers temporaires.

L’erreur la plus coûteuse est d’oublier ce cloisonnement. On finit avec des droits identiques sur tout, ce qui donne à l’écriture un rayon d’action trop vaste.

image

Deux réglages qui font gagner beaucoup, sans magie

Il existe des ajustements qu’on peut réaliser sans complexifier à l’excès. Ce sont souvent des gains de sécurité indirects, mais solides.

D’abord, éviter les écritures globales depuis PHP, en réduisant les répertoires en écriture au strict nécessaire. Ensuite, imposer une cohérence de permissions après déploiement et après restauration.

Pour rendre ça concret, voici comment je fais généralement la différence entre une configuration “qui rassure” et une configuration “qui protège vraiment” :

    Une configuration qui corrige l’erreur d’écriture en augmentant tout l’espace de permissions, mais sans vérifier le périmètre réel de ce qui devient écrivable. Une configuration qui limite l’écriture aux répertoires utilisés par WordPress et les plugins nécessaires, puis qui teste les mises à jour et la production. Une configuration qui tient compte de la configuration serveur (interprétation PHP, règles d’accès, execution restrictions), pas uniquement des permissions Unix.

Le point important : la sécurité n’est pas un seul levier, c’est l’alignement de plusieurs. Les permissions sont une base. Elles deviennent beaucoup plus efficaces quand elles s’accordent avec la configuration serveur et les pratiques de déploiement.

L’angle mort : permissions et transferts (FTP, outils, sauvegardes)

Les transferts peuvent ruiner votre travail. Un simple upload via un client FTP peut changer des modes ou la propriété des fichiers, parfois de manière discrète. J’ai vu des projets où https://gardewp.fr/securite-wordpress/ seule une poignée de fichiers se retrouvait “à part”, et c’est justement ce petit groupe qui a permis une exploitation.

Les causes typiques :

    changement d’utilisateur lors du transfert, réglage de mode par défaut côté client, restauration de backup qui réapplique des propriétaires différents, scripts de déploiement qui ne conservent pas certains attributs.

C’est pour ça qu’un site pro devrait idéalement avoir une procédure de “post-deploy” qui valide les permissions de manière automatisée, au moins sur les zones critiques. Pas besoin d’un truc lourd, mais une vérification régulière évite les dérives silencieuses.

Quand trop verrouiller casse WordPress, et quoi faire

Il y a un scénario assez courant : vous resserrez les droits, puis WordPress ne peut plus écrire dans wp-content ou refuse les mises à jour. Les symptômes ressemblent à un blocage administratif. Les erreurs exactes dépendent du type de mécanisme d’écriture utilisé, mais le fond est le même : PHP n’a plus les droits attendus.

Le réflexe sain est de ne pas “largir tout”. Je procède plutôt par ciblage :

    identifier le répertoire exact où l’écriture échoue, vérifier si ce répertoire doit être writable en conditions normales, rétablir l’écriture uniquement sur ce point, puis re-tester les actions qui déclenchent l’erreur (mises à jour, uploads, activation de plugin).

C’est aussi un bon moment pour relire la pratique de votre hébergeur. Certains environnements ont des contraintes spécifiques (chroot, restrictions PHP-FPM, choix d’utilisateurs). Sur un hébergement partagé, vous pouvez avoir moins de marge, et vous devez vous aligner sur leur modèle de sécurité.

Une politique de permissions réaliste, orientée risque

La bonne approche n’essaie pas de rendre tout immobile. Elle réduit la surface d’attaque, tout en gardant le site maintenable.

image

Un schéma mental utile :

    ce qui n’a jamais besoin d’être modifié par le serveur via PHP ne doit pas être writable, ce qui doit être modifié doit l’être dans un périmètre minimal, ce qui doit être exécuté ne doit pas être accessible comme une zone d’upload “au hasard”.

Quand cette logique est respectée, même une faiblesse applicative a moins d’espace pour se transformer en dégâts. Le site peut rester opérationnel, et les tentatives d’injection se heurtent à une limite système.

Et c’est exactement ce que vous cherchez avec une sécurité site WordPress professionnel : ne pas seulement réagir aux incidents, mais rendre certains scénarios beaucoup moins rentables pour un attaquant.

Petit test pratique, façon audit interne

Sans outillage exotique, vous pouvez faire un audit interne pragmatique avant et après un changement de permissions. L’objectif n’est pas de cocher des cases. C’est de vérifier l’impact réel.

Je le fais en deux temps : observation, puis validation.

D’abord, je repère les zones d’écriture attendues, uploads et caches principalement. Ensuite, je fais une série de vérifications fonctionnelles, par exemple un upload d’image, l’activation d’un plugin de cache en test, puis une mise à jour sur staging. Si tout passe, je ne touche pas à “plus”, je consolide.

Ce qui m’a le plus appris dans les projets pro, c’est qu’une amélioration de sécurité doit être accompagnée d’une preuve de maintien. Sinon, les équipes finissent par revenir en arrière en cas de friction.

Pièges classiques à éviter (ceux qui reviennent en production)

Il existe quelques pièges récurrents, faciles à commettre quand on intervient en urgence.

Le premier, c’est de confondre “réparer” et “durcir”. Si WordPress ne met pas à jour, vous devez d’abord comprendre où l’écriture échoue. Mettre en global un répertoire en 777 peut régler l’urgence, mais vous avez supprimé une barrière de sécurité.

Le deuxième, c’est de “corriger maintenant, réappliquer jamais”. Or, après une restauration, vos droits peuvent changer. Si votre procédure ne revalide pas l’état des permissions, vous perdez les gains.

Le troisième, c’est d’oublier les fichiers persistants liés aux plugins. Certains plugins stockent des logs ou des fichiers temporaires. D’autres génèrent des caches. Ce sont souvent eux qui nécessitent des exceptions limitées.

Ce ne sont pas des détails : ce sont les raisons pour lesquelles le durcissement échoue ou réussit.

Conclusion de fait : la sécurité vient du périmètre

La contrainte de fichiers et les permissions ne sont pas un sujet “technique pour technique”. C’est une traduction directe de la politique de confiance sur votre serveur. En limitant qui peut écrire et où, vous réduisez la capacité d’un attaquant à transformer une faille en compromission.

Sur un site WordPress professionnel, j’ai vu les meilleurs résultats venir d’une combinaison simple : un périmètre d’écriture réduit, une cohérence de propriétaire et de groupe, une validation après déploiement ou restauration, et une attention particulière aux répertoires comme wp-content/uploads.

Si vous ne retenez qu’une idée, gardez celle-ci : une permission doit avoir une raison. L’objectif n’est pas d’obtenir la configuration la plus “dure” possible, c’est d’obtenir la configuration la plus utile pour votre modèle de risque, sans casser la maintenance.