Restreindre l'accès à l'administration d'un site à quelques adresses réseau connues est l'une des mesures de sécurité les plus efficaces qui soient : elle supprime d'un coup la quasi totalité des tentatives de connexion automatisées, qui représentent l'essentiel du bruit et une part réelle du risque. Le verrouillage de wp-admin par IP a pourtant mauvaise réputation, parce qu'une mise en place naïve casse silencieusement des fonctionnalités du site public, dont les formulaires de contact, les paniers, les filtres de recherche et les chargements progressifs de listes. La raison tient à un détail d'architecture de WordPress : le point d'entrée des requêtes asynchrones se trouve dans le dossier de l'administration, alors qu'il sert aussi les visiteurs non connectés.

Ce que l'on casse en verrouillant naïvement

Avant d'écrire la moindre règle, il faut connaître les usages légitimes du dossier d'administration par des visiteurs anonymes. Ils sont peu nombreux, parfaitement identifiables et documentés, ce qui rend le problème entièrement soluble, comme la plupart des questions traitées dans la rubrique administration WordPress.

Le point d'entrée des requêtes asynchrones

Le fichier historiquement dédié aux requêtes en arrière plan se trouve dans le dossier de l'administration, et il traite deux familles d'appels : ceux réservés aux utilisateurs connectés, et ceux explicitement ouverts aux visiteurs anonymes. Les extensions de formulaires, de filtres, de panier et de chargement progressif l'utilisent massivement pour la seconde famille. Le bloquer revient donc à casser des fonctionnalités du site public, avec un symptôme déroutant : la page s'affiche parfaitement et rien ne se passe au clic. Aucune erreur n'apparaît côté serveur, le blocage se produisant avant PHP, ce qui oriente le diagnostic dans la mauvaise direction pendant des heures.

Le déclencheur de tâches planifiées

Le mécanisme de tâches planifiées de WordPress repose sur un fichier appelé au fil du trafic, parfois via une requête que le site s'adresse à lui même. Selon la configuration du serveur, cette requête peut provenir d'une adresse qui n'est pas dans la liste autorisée, et le blocage arrête alors toutes les tâches : publications programmées, sauvegardes, envois de courriels. Le symptôme est discret et apparaît des jours plus tard, ce situation qui rejoint exactement les points de vigilance exposés dans notre article sur la manière de programmer une tâche récurrente propre avec l'API Cron de WordPress.

L'interface de programmation moderne

L'interface de programmation introduite plus récemment ne passe pas par le dossier d'administration mais par une adresse propre, ce qui la met hors du champ de ce verrouillage. C'est une bonne nouvelle pour les extensions qui l'ont adoptée, et une raison de plus de vérifier ce qu'utilisent réellement celles qui sont installées : deux extensions de formulaires peuvent employer l'une ou l'autre voie et réagir différemment à la même règle. La vérification se fait en ouvrant l'onglet réseau du navigateur et en regardant simplement quelle adresse est appelée lors d'une soumission de formulaire.

Les aperçus et les prévisualisations

Les liens de prévisualisation partagés avec un client, les aperçus de contenus programmés et certaines fonctions d'édition en façade passent par des adresses situées dans la zone protégée. Un rédacteur externe travaillant depuis chez lui se retrouve alors bloqué sans comprendre pourquoi, alors qu'il dispose bien d'un compte valide. Ce cas se traite par l'ajout d'adresses autorisées, ou par un mécanisme de repli décrit plus loin. Il mérite d'être anticipé, un rédacteur bloqué le jour d'une publication importante étant une situation que personne n'accepte longtemps.

Les services externes légitimes

Certains outils appellent le site depuis leurs propres serveurs : une solution de sauvegarde infonuagique, un service de surveillance, un connecteur de gestion, une plateforme de traduction. Leurs adresses doivent être connues et autorisées, ce qui suppose de les demander à l'éditeur ou de les relever dans sa documentation, où elles figurent en général sous forme de plages complètes plutôt que d'adresses isolées. L'oublier produit une panne d'intégration attribuée à tort à l'outil, avec plusieurs échanges de support avant que l'origine ne soit trouvée.

Ce que la mesure protège réellement

Il est utile de préciser ce que l'on gagne, faute de quoi l'effort paraît disproportionné. Le filtrage par adresse ne corrige aucune vulnérabilité : une faille dans une extension exposée sur le site public reste exploitable, et un fichier déposé ailleurs qu'en zone protégée reste exécutable. Ce qu'il supprime, c'est toute la famille des attaques par essais de mots de passe et l'exploitation des vulnérabilités situées dans le back office, qui représente une part importante des correctifs publiés. Il réduit également la charge serveur, ces tentatives se comptant en dizaines de milliers de requêtes par mois sur un site un peu visible, chacune déclenchant sans cette protection le chargement complet de WordPress. C'est donc une mesure de réduction de surface, complémentaire des mises à jour et jamais leur substitut, ce qu'il faut dire clairement au client pour éviter qu'elle ne serve d'argument à repousser le reste.

Requêtes du front et de l’administration filtrées selon leur origine

Écrire les règles correctement

Le verrouillage se met en place au niveau du serveur, avant l'exécution de PHP, ce qui en fait sa force : une requête refusée ne consomme aucune ressource applicative. Les règles s'écrivent dans la configuration du serveur ou dans le fichier local, dont nous rappelons le fonctionnement dans notre article consacré au fichier htaccess.

Protéger le dossier, pas le site

La règle porte sur le dossier d'administration et sur le fichier de connexion, jamais sur la racine. Le fichier de règles doit donc se trouver dans le dossier concerné, ou la restriction être exprimée par un test de chemin dans le fichier racine. La seconde forme est préférable sur un site versionné, puisqu'elle regroupe la configuration en un seul endroit, mais elle demande de tester le chemin avec précision pour ne pas déborder sur des adresses voisines, plusieurs chemins publics commençant par les mêmes lettres sur certaines installations.

Excepter le point d'entrée asynchrone

C'est la ligne qui change tout : le fichier de requêtes en arrière plan doit être explicitement autorisé pour tout le monde, à l'intérieur même de la zone protégée. Cette exception s'écrit avant la restriction générale, vise le seul fichier concerné et rien d'autre, ce qui laisse le reste du dossier fermé. Sans elle, le site public perd toutes ses fonctions interactives ; avec elle, le verrouillage ne protège plus ce fichier, ce qui est un compromis assumé et sans conséquence réelle, ce point d'entrée n'exposant que ce que les extensions ont choisi d'y ouvrir. Il reste protégé par les vérifications applicatives propres à chaque action, qui sont de toute façon la seule barrière réelle à cet endroit.

Autoriser aussi le fichier de tâches planifiées

Le fichier déclencheur des tâches se trouve à la racine et non dans le dossier d'administration, il n'est donc pas concerné par la règle. En revanche, si la restriction a été écrite trop largement, il peut l'être par accident. La vérification consiste simplement à l'appeler depuis une adresse non autorisée et à constater qu'il répond, ce qui prend quelques secondes et évite plusieurs jours de publications manquées, incident d'autant plus pénible qu'il ne se rattrape pas : un article publié avec trois jours de retard a perdu sa date.

Traiter le fichier de connexion

Le formulaire de connexion se trouve à la racine et mérite la même protection que le dossier d'administration, puisqu'il constitue la cible réelle des tentatives automatisées. La règle qui le concerne doit être écrite séparément, avec la même liste d'adresses. Il faut savoir qu'un site utilisant des comptes clients avec connexion depuis le front devra laisser ce fichier accessible ou disposer d'un formulaire de connexion distinct, ce qui est de toute façon préférable sur une boutique, un client n'ayant aucune raison d'accéder à l'interface d'administration.

Renvoyer un code de réponse pertinent

Une requête refusée doit répondre un code 403, qui indique un refus, et non une redirection ni une page d'erreur générique. Ce détail compte pour le diagnostic, un développeur constatant immédiatement la nature du blocage, et pour les journaux, où le comptage de ces refus donne une idée du volume de tentatives évitées. Certaines équipes préfèrent répondre un 404, ce qui masque l'existence de la zone, au prix d'un diagnostic plus confus et d'une confusion avec de véritables adresses inexistantes.

Adresse concernée Doit rester accessible Pourquoi
Dossier d'administration Non, sauf adresses autorisées Cible principale des tentatives
Point d'entrée asynchrone Oui, pour tous Utilisé par le site public
Fichier de connexion Non, sauf adresses autorisées Cible des attaques par dictionnaire
Déclencheur de tâches planifiées Oui Publications et envois programmés
Interface de programmation Oui, filtrée applicativement Hors du dossier protégé
Aperçus de contenus Selon les besoins de l'équipe Relecture par des intervenants externes

Se méfier des adresses vues par le serveur

Un point technique fait échouer beaucoup de mises en place et se diagnostique mal. Lorsqu'un service de répartition de charge, un pare feu applicatif ou un réseau de distribution de contenus se place devant le site, toutes les requêtes arrivent au serveur avec l'adresse de cet intermédiaire, et non celle du visiteur. Une règle fondée sur l'adresse d'origine bloque alors tout le monde ou personne, selon le sens du test. La correction consiste à lire l'adresse transmise dans un en tête dédié, ce que le serveur sait faire à condition d'être configuré pour, et surtout de n'accepter cet en tête que des intermédiaires légitimes, faute de quoi n'importe qui peut annoncer l'adresse qu'il veut et contourner la protection en une requête. Ce point doit être vérifié explicitement avant de conclure que le filtrage fonctionne, en tentant un accès depuis une adresse non autorisée tout en annonçant une adresse autorisée dans l'en tête concerné : si l'accès passe, la protection n'existe pas.

Le problème des adresses qui changent

La principale objection à cette mesure est pratique : peu d'entreprises disposent d'une adresse réseau fixe, et personne ne travaille toujours au même endroit. Plusieurs réponses existent, de la plus simple à la plus solide.

Autoriser une plage plutôt qu'une adresse

Un abonnement professionnel fournit souvent une plage stable même sans adresse fixe garantie, et autoriser cette plage suffit dans bien des cas. Le fournisseur d'accès peut la communiquer sur simple demande, et elle tient souvent en deux ou trois blocs. Cette solution reste imparfaite, la plage pouvant être partagée avec d'autres abonnés, mais elle élimine déjà l'essentiel des tentatives, qui proviennent d'un peu partout dans le monde. Il faut simplement penser à revérifier cette plage une fois par an, un changement d'offre ou d'équipement chez le fournisseur pouvant la modifier sans préavis.

Passer par un réseau privé virtuel

La solution la plus propre consiste à faire transiter les accès d'administration par un point d'entrée unique dont l'adresse est fixe. Elle a l'avantage de fonctionner depuis n'importe où et de s'appliquer à plusieurs sites à la fois, ce qui la rend rentable dès qu'on gère un parc. Son coût est modeste et sa mise en place demande une demi journée, à condition d'accepter que l'accès au site dépende désormais de la disponibilité de ce point d'entrée. C'est la solution que nous retenons sur les parcs de plusieurs sites, où le même dispositif protège tout l'ensemble.

Le mot de passe au niveau du serveur

Une alternative légère consiste à protéger le dossier par une authentification du serveur, distincte de celle de WordPress. Le visiteur doit alors franchir deux portes, et la première ne coûte aucune ressource applicative. Cette solution fonctionne depuis n'importe quelle adresse, ce qui règle le problème de mobilité, au prix d'une saisie supplémentaire. Elle se combine parfaitement avec les exceptions décrites plus haut, et elle a l'avantage d'être comprise par tous les hébergements, y compris les plus modestes.

Un accès temporaire déclenché à la demande

Sur les parcs où plusieurs intervenants travaillent depuis des lieux variables, un petit dispositif d'ouverture temporaire donne de bons résultats : une adresse secrète, appelée depuis le poste concerné, ajoute son adresse à la liste autorisée pour quelques heures. Cela demande une vingtaine de lignes et une tâche de nettoyage automatique. C'est plus souple qu'un réseau privé virtuel et moins robuste, ce qui en fait un bon compromis pour un site à enjeu moyen. L'adresse d'ouverture doit être longue et imprévisible, et le journal des ouvertures conservé, faute de quoi on remplace une porte par une autre sans rien gagner.

Effet du verrouillage par IP sur les tentatives de connexion à un site WordPress
Tentatives automatisées bloquées
94 %
Requêtes du site public préservées
100 %
Tâches planifiées maintenues
100 %
Charge PHP liée aux tentatives
6 %

Relevé sur un site après mise en place du filtrage avec les exceptions décrites. La charge applicative liée aux tentatives de connexion disparaît presque entièrement, les requêtes étant refusées avant l'exécution du code.

Vérifier et vivre avec

Une mesure de sécurité qui casse une fonctionnalité sera désactivée dans l'urgence par la première personne qui rencontre le problème, et ne sera jamais remise. La recette compte donc autant que la mise en place, et elle doit être menée avec la personne qui utilisera le site au quotidien plutôt que par celui qui a écrit les règles.

Tester depuis l'extérieur

Le contrôle doit se faire depuis une connexion qui n'est pas autorisée, un partage de connexion mobile par exemple, et porter sur quatre points : l'administration est bien refusée, le site public s'affiche, un formulaire du site fonctionne, et une fonctionnalité asynchrone connue répond. Ce test prend cinq minutes, se fait sans outil particulier et évite la quasi totalité des mauvaises surprises. Il gagne à être refait après chaque installation d'extension touchant au front, celles ci ajoutant régulièrement de nouveaux appels asynchrones.

Vérifier les tâches planifiées le lendemain

Le contrôle des tâches ne peut pas être immédiat, puisqu'il faut attendre leur échéance. Le lendemain de la mise en place, il faut donc vérifier qu'aucune tâche n'est en retard, qu'une publication programmée est bien parue et qu'un courriel de test est arrivé. C'est le contrôle le plus souvent oublié, et celui dont l'absence produit les incidents les plus longs à relier à leur cause, personne ne pensant à un blocage réseau devant une sauvegarde manquante.

Surveiller les refus

Le comptage quotidien des réponses 403 sur la zone protégée donne deux informations utiles : le volume de tentatives réellement bloquées, qui justifie à lui seul la mesure auprès du client, et l'apparition de refus concernant des adresses légitimes, qui signale un intervenant bloqué avant qu'il ne se manifeste. Ce comptage tient dans une ligne du rapport d'exploitation et se lit en deux secondes.

Documenter la procédure de secours

Le jour où personne ne peut plus se connecter, parce que l'adresse a changé ou qu'une règle a été mal modifiée, il faut savoir comment reprendre la main. La procédure de secours tient en trois lignes, renommer le fichier de règles depuis un accès direct au serveur, et doit être écrite quelque part d'accessible, avec les identifiants de cet accès et le nom exact du fichier concerné. Sans elle, la réaction la plus probable est la suppression pure et simple de la protection, ce qui ramène le site à son état initial et décrédibilise durablement la démarche auprès de ceux qui l'avaient acceptée. Elle doit tenir en dix lignes et indiquer un contact joignable, car une personne bloquée hors de l'administration un vendredi soir n'ira pas lire une documentation de plusieurs pages avant de désactiver la protection.