Quand on parle de protection WordPress, on pense souvent aux thèmes, aux plugins et aux mises à jour. C’est logique, parce que ce sont eux qui donnent du volume à l’attaque. Mais dans la vraie vie, le point faible le plus banal reste l’accès “côté serveur”. Un accès SSH ou SFTP trop large, avec un compte partagé, une authentification faible, ou des permissions mal pensées, suffit à transformer un site “normal” en surface d’escalade.
J’ai vu des cas où un site était impeccablement patché, jusqu’au moment où quelqu’un a obtenu un accès SFTP avec un mot de passe réutilisé depuis un autre service. Le résultat n’a pas été spectaculaire tout de suite, mais en quelques jours, les fichiers modifiés ont servi de base à une persistance. À ce stade, la restauration ne sert plus seulement à “réparer”, elle sert aussi à comprendre comment on en est arrivé là.
L’objectif de ce billet est simple: rendre l’accès SSH/SFTP plus strict, plus prévisible, et plus difficile à exploiter. On va aussi parler des compromis, parce que certaines durcissements compliquent le déploiement ou le support, et il faut savoir où mettre le curseur.
Le vrai risque: ce que l’accès SSH/SFTP permet
SSH et SFTP ne sont pas “équivalents” en termes de risque, mais ils partagent une idée: qui contrôle l’accès au système de fichiers, contrôle une grande partie du destin du site.
Avec SSH, selon la configuration, l’attaquant peut tenter:
- d’exécuter des commandes pour lire des clés, des fichiers de configuration, des variables d’environnement d’installer un outil de persistance, un bot ou un service de remonter en privilèges si les permissions et les rôles sont mal dessinés
Avec SFTP, l’attaque est souvent plus “silencieuse”: si l’utilisateur peut écrire au bon endroit, il peut déposer un webshell, modifier un plugin, altérer un fichier PHP ou injecter un code dans une zone qui sera ensuite servie. Même sans exécution directe, l’échelle de temps est parfois plus longue, mais le modèle reste le même: l’accès au stockage devient un levier.
La clé est donc moins “SSH vs SFTP”, que “qui a le droit de lire et d’écrire, et où”.
Commencer par l’inventaire: comptes, rôles, et chemins
Avant de modifier quoi que ce soit, il faut répondre à trois questions, sans supposer.
Première question: combien de comptes ont accès à SSH/SFTP, et à quoi servent-ils réellement? Un compte “admin” qui sert à tout, parce que c’était pratique, est une dette technique classique. Quand la personne quitte l’équipe ou perd l’accès, ce compte devient une porte trop grande.
Deuxième question: quels répertoires peuvent-ils toucher? Un compte qui peut écrire partout dans l’arborescence du serveur, même si c’est “juste pour transférer des fichiers”, crée des scénarios dangereux. En WordPress, on veut que l’écriture cible soit généralement limitée à wp-content et parfois à certains dossiers spécifiques de déploiement.
Troisième question: quel est le mécanisme d’accès actuellement utilisé? Mot de passe, clé SSH, ou les deux. Et aussi, si vous utilisez du NAT, un proxy, un bastion, ou une console de panel d’hébergement, il faut savoir où se place le contrôle réel.
Ce mini-inventaire évite un piège fréquent: verrouiller SSH, puis découvrir que votre pipeline de déploiement ou votre outil SFTP a besoin d’un mode de fonctionnement plus permissif. On évite ainsi les “verrous” qui cassent la production pour des raisons évitables.
Remplacer le mot de passe par des clés SSH (et les gérer)
Le plus gros gain de sécurité vient presque toujours de la même action: désactiver l’authentification par mot de passe et n’autoriser que des clés SSH.

Je sais, ça semble “évident”, mais dans les environnements historiques, le mot de passe reste actif parce que quelqu’un l’a “oublié” ou parce que le formulaire de connexion ne propose pas encore la logique des clés. Le problème, c’est que les attaques sur les mots de passe ne demandent pas de créativité: elles exploitent la répétition et la persistance.
Pour une gestion saine des clés:
- créez des paires de clés distinctes par personne ou par système (pas une seule clé partagée) utilisez un nom de clé et une convention claire pour savoir qui fait quoi supprimez ou bloquez les clés quand un accès n’est plus nécessaire
Attention aux cas particuliers. Si vous avez des automations, un compte de déploiement “machine” est souvent pertinent. Mais évitez de mettre les clés machine dans un dossier accessible à tout le monde sur votre poste de travail. Une mauvaise hygiène locale revient vite dans le serveur.
Bonus réaliste: interdire la connexion directe pour le compte web
Un pattern que j’aime bien en WordPress: le compte “web” (le même user que le processus PHP-FPM ou Apache) ne devrait pas être celui avec lequel on se connecte en SSH. Le rôle de ce compte est de servir l’application. Le rôle d’un compte d’administration est de déployer et réparer, pas de vivre au contact du runtime.
En pratique, on utilise un user d’administration, avec un accès restreint, et on fait en sorte que l’écriture dans WordPress soit compatible avec les permissions. Si vous avez des erreurs de droits, c’est souvent un signe que les permissions ont été configurées “pour que ça marche”, pas “pour que ça reste sûr”.
Verrouiller l’accès réseau: limites, filtrage, et latence acceptable
Le verrouillage réseau est un second levier très efficace. Plutôt que d’exposer SSH à tout le monde, on limite le nombre de sources autorisées.
Souvent, la première mesure utile consiste à restreindre SSH à des IP connues, par exemple les IP de l’équipe ou du bastion. Si votre équipe est répartie avec des réseaux variables, on peut utiliser des plages raisonnables ou un VPN d’administration. Le compromis est simple: plus on verrouille, plus on réduit le risque, mais plus il faut prévoir l’accès en mobilité.
Une stratégie robuste consiste à n’avoir qu’un seul point d’entrée contrôlé, puis à relayer vers les serveurs internes. Cela peut être un bastion hébergé dans votre infra, ou un service d’accès sécurisé fourni par votre hébergeur. Le point important est de ne pas transformer chaque serveur en cible ouverte sur Internet.
À noter, si vous utilisez un firewall comme UFW, firewalld, ou des règles au niveau du système, appliquez-les avec soin. Une erreur de règle peut couper votre session actuelle. Je recommande de travailler avec une session de secours et un plan de rollback, surtout sur des serveurs distants.
Réduire les droits: permissions et ownership sur WordPress
Une configuration SSH “sécurisée” ne sert pas à grand-chose si le compte SFTP peut écrire un fichier n’importe où, y compris des emplacements qui contournent le contrôle applicatif.
L’idée de base: le compte d’accès doit pouvoir:
- écrire dans wp-content (et seulement ce qui est requis) éventuellement éditer certains fichiers de configuration spécifiques liés au déploiement ne pas avoir de droits sur des zones sensibles du système
Sur WordPress, les endroits où un attaquant veut écrire ne manquent pas: wp-content/plugins, wp-content/themes, wp-content/uploads, parfois wp-content/mu-plugins. Si votre utilisateur d’accès peut écrire sur tous ces chemins, c’est déjà un risque intrinsèque. Mais l’objectif n’est pas de rendre l’écriture impossible. L’objectif est de rendre l’écriture plus difficile à détourner.
Dans un monde parfait, on combine permissions minimales avec des contrôles supplémentaires, comme:
- empêcher l’exécution depuis des répertoires qui ne devraient pas exécuter de PHP séparer le stockage des fichiers statiques et l’endroit où PHP s’exécute contrôler les ownership pour éviter les écritures “trop larges”
Je vois souvent des environnements où tout est en www-data ou tout est en “admin”, ce qui rend l’administration pratique mais la sécurité fragile. Un compromis raisonnable est souvent d’avoir un ownership cohérent pour WordPress, et un compte d’administration qui n’a pas les mêmes privilèges que le runtime.
Chroot SFTP, ou comment limiter l’arborescence visible
Pour les accès SFTP, le chroot est une option intéressante: on “enferme” l’utilisateur dans un sous-répertoire, de manière à ce qu’il ne puisse pas naviguer plus haut dans l’arborescence système.
Ce mécanisme réduit la surface d’attaque. Même si un attaquant obtient des identifiants SFTP valides, il se retrouve dans un environnement limité. Cela ne rend pas l’écriture dans WordPress “inoffensive”, mais cela empêche l’exploration de fichiers système et limite la capacité à lire des secrets.
Le chroot SFTP demande une configuration sérieuse, parce qu’il faut gérer la structure de répertoires et les permissions côté système. Selon votre distribution et votre configuration OpenSSH, cela peut aussi impacter certains outils de transfert ou de sauvegarde. Mon conseil pratique: testez sur un serveur de staging, puis appliquez graduellement.
Si vous n’êtes pas prêt pour un chroot complet, une alternative partielle consiste à limiter les permissions du répertoire de destination et à empêcher les écritures hors périmètre. Ça ne remplace pas le chroot, mais c’est déjà un net progrès.
Fail2ban et durcissement SSH: utile, mais pas magique
Les attaques automatisées frappent SSH et, plus rarement, SFTP. Mettre en place un mécanisme de bannissement après un certain nombre d’échecs aide à réduire le bruit et la charge, et ça peut ralentir certains scénarios.
Fail2ban, ou un équivalent, est utile, mais ne remplace pas les mesures de fond: clés SSH, restrictions réseau, désactivation du mot de passe, et permissions strictes.
Un point à garder en tête: si vous travaillez depuis un réseau d’entreprise avec NAT agressif, vous risquez de bannir des utilisateurs légitimes en cas d’échecs répétitifs. Le bon réglage dépend de la réalité du trafic et des erreurs humaines. Sur un accès d’administration, je préfère un seuil plus prudent, quitte à laisser passer un peu plus de bruit.
Déploiement WordPress: séparer “transférer” et “servir”
Un détail qui change tout: assurez-vous que le processus de déploiement et le processus de service ne partagent pas aveuglément les mêmes droits.
Dans beaucoup de setups WordPress, on transfère des fichiers https://gardewp.fr/securite-wordpress/ dans wp-content, puis on laisse PHP servir. Si le compte SFTP est identique au compte runtime, alors une compromission du compte d’accès devient une compromission “directe” du runtime.
Sans aller jusqu’à une architecture multi-comptes complexe, vous pouvez déjà renforcer la séparation en:
- utilisant un user dédié pour le déploiement laissant le runtime user gérer uniquement l’exécution évitant les permissions trop ouvertes, notamment en écriture sur des dossiers que vous n’avez pas besoin d’éditer
Le résultat recherché est que même si un compte d’accès est “gagné”, l’attaquant n’obtienne pas automatiquement le même niveau de privilège qu’un utilisateur système déjà très proche de l’exécution.
Exemple concret: “je peux me connecter, donc je suis en sécurité”
Un exemple fréquent d’illusion: “j’ai un compte avec accès SFTP, mais je ne fais que transférer. Donc c’est bon”. Sauf que l’authentification valide est exactement ce dont un attaquant a besoin.
Je me souviens d’un cas où un développeur transférait via SFTP depuis un ordinateur portable. Le mot de passe était fort, et le site WordPress était à jour. Le problème ne venait pas de WordPress. Il venait d’un vieux client SFTP où l’identifiant restait enregistré, et d’une réutilisation de mot de passe ailleurs. Le jour où l’ordinateur a été compromis, l’accès SFTP a été utilisé pour déposer un script dans wp-content/uploads avec un nom peu suspect. Le site semblait normal au début, puis l’injection a commencé à servir du contenu.
Leçons: l’accès est un vecteur. On sécurise l’accès, mais on sécurise aussi l’intrusion possible en réduisant les droits et en limitant l’arborescence.
Checklist de durcissement (sans casser votre travail)
Voici les actions qui ont le meilleur ratio effort-risque dans des environnements WordPress classiques. Elles sont dans l’ordre où je les fais, parce que les dépendances sont moins pénibles.
- basculer l’authentification SSH vers les clés, puis désactiver le mot de passe restreindre l’accès SSH à un périmètre réseau (IP, VPN d’administration, bastion) créer un compte d’administration dédié pour le déploiement, éviter d’utiliser le compte runtime limiter les permissions, en autorisant l’écriture uniquement là où WordPress doit être modifié (souvent wp-content) pour SFTP, activer un chroot quand c’est possible, ou au minimum enfermer l’utilisateur dans un répertoire dédié
Si une étape vous bloque, c’est souvent le signe que l’environnement a besoin d’un ajustement plus profond (ownership, droits sur dossiers, méthode de déploiement). L’idée n’est pas de “forcer”, c’est de rendre l’accès à la fois fonctionnel et borné.
Limiter les accès: comptes individuels, rotation, et suppression
Limiter les accès, ce n’est pas seulement “restreindre qui peut se connecter”. C’est aussi rendre les connexions “non réutilisables”.
Sur les comptes individuels: dès qu’un rôle change, vous devez pouvoir retirer l’accès rapidement. Ça implique un process interne clair, sinon vous êtes bloqué par l’inertie. Dans les équipes, c’est souvent le problème numéro un. Le serveur est sécurisé, mais la gouvernance du compte ne l’est pas.

Sur la rotation: ce n’est pas obligatoire tous les jours, mais ça doit exister comme pratique. Pour les clés SSH, la rotation a du sens quand un poste est remplacé, qu’un prestataire change, ou quand vous suspectez une fuite.
Sur la suppression: un vieux compte “juste au cas où” est une porte qui ne se ferme jamais. Si vous supprimez un compte et que personne ne s’en rend compte après quelques semaines, c’est généralement un bon signe que le compte n’était pas nécessaire.
SFTP vs SSH: choisir l’outil en fonction du besoin réel
On peut se retrouver avec deux usages différents:
- l’écriture de fichiers (uploads, déploiement de thèmes, plugins) la maintenance (corriger des permissions, vérifier des logs, redémarrer des services)
Si votre usage principal est l’écriture de fichiers, SFTP peut suffire, surtout s’il est limité (chroot, permissions minimales). Si vous avez besoin d’actions administratives fréquentes, SSH sera nécessaire, mais avec un périmètre strict.
Je recommande de ne pas “ouvrir SSH pour tout” par confort. On finit par utiliser SSH comme outil universel, et on perd la discipline. La discipline, c’est ce qui maintient la sécurité sur la durée.
Journalisation: repérer avant que ce soit trop tard
Un serveur peut être bien verrouillé et quand même avoir un incident, parce que l’erreur humaine existe, parce que des clés peuvent être exposées, parce qu’un plugin peut être compromis côté applicatif. La journalisation sert à détecter.
Ce que je surveille généralement dans ce type de configuration:
- les tentatives de connexion SSH ratées, et les patterns (horaires, IP, volume) les connexions réussies, avec l’identité utilisateur les opérations de fichiers sensibles (selon votre infra, cela peut être plus ou moins accessible)
Les journaux aident aussi à valider que vos règles fonctionnent. Par exemple, après avoir désactivé le mot de passe, on doit voir moins de patterns d’échec de ce type. Si vous voyez encore des échecs “mot de passe”, c’est parfois un signe que la configuration n’est pas appliquée partout (ou qu’un autre service, ou un bastion, re-route autrement).
Cas limites qui méritent une décision
Il y a des situations où la “meilleure pratique” est moins évidente.
Première situation: le déploiement automatisé depuis un CI. Si le pipeline doit accéder au serveur, vous avez besoin d’un compte machine, avec une clé dédiée. Là, le bon choix n’est pas “ouvrir les permissions”, c’est “encapsuler” l’accès dans une identité de machine, et réduire ses droits au minimum requis.
Deuxième situation: la gestion des permissions sur WordPress. WordPress, selon la configuration et les plugins, peut demander l’écriture dans certains dossiers. Si vous verrouillez trop tôt, vous allez rencontrer des erreurs pendant l’upload de médias ou l’installation de thèmes. Le remède consiste souvent à ajuster les ownership et les permissions “ciblées”, pas à réouvrir SSH en grand.
Troisième situation: plusieurs environnements (prod, staging). Une clé ou un compte utilisé partout multiplie l’impact d’une fuite. La discipline des identités par environnement est un détail qui protège beaucoup.
La sécurité n’est pas un état, c’est une habitude
La meilleure protection WordPress en matière d’accès SSH/SFTP, c’est celle qui tient dans le temps. Ce qui se casse le plus souvent, ce n’est pas la technique, c’est le processus: un accès oublié, une clé partagée, un compte “pour dépanner” qui reste en place.
Une approche simple consiste à documenter qui a accès, pourquoi, et comment on retire l’accès. Pas besoin d’un document long. Juste assez pour que, quand quelqu’un change de poste ou qu’un prestataire s’arrête, l’accès soit retiré sans négociation.
Voici une règle pratique que j’applique souvent: si un accès n’est pas utilisé régulièrement, soit il doit être supprimé, soit il doit avoir un canal plus strict, soit il doit avoir des droits plus limités. Le but n’est pas de vivre en mode parano, c’est de garder le serveur dans un état “compréhensible”.
Vérifier rapidement que tout est cohérent
Une dernière étape utile, avant de considérer le sujet “réglé”: valider que votre configuration correspond à votre intention.
Le scénario idéal, c’est:
- vous connectez avec une clé, pas un mot de passe vous voyez des accès entrants uniquement depuis vos zones autorisées votre compte d’administration ne peut écrire que dans les dossiers attendus le runtime WordPress n’est pas celui que vous utilisez en SSH SFTP est limité, et le chroot, s’il est activé, ne permet pas d’exploration
Je ne donne pas ici de commandes précises, parce que la configuration varie selon votre distribution, votre niveau d’accès, et l’hébergement. Mais le principe reste constant: faites correspondre les permissions réelles et les droits théoriques, sinon vous créez un “carré magique” où quelqu’un pensera que tout est verrouillé alors que ce n’est pas le cas.
Si vous avez la moindre zone floue, traitez-la comme un bug de sécurité. Ce genre de détail ne se voit pas dans la page d’accueil, mais il se voit dans les journaux et, parfois, après coup.
Si vous voulez, décrivez votre contexte (hébergeur, OS, usage CI/CD, comptes actuels, si vous utilisez déjà des clés SSH ou un bastion). Je peux vous proposer une stratégie de durcissement adaptée, avec un plan de migration étape par étape, pour éviter de casser vos accès en production.
