Sécuriser WordPress : limiter les tentatives de connexion

WordPress reçoit des attaques depuis longtemps, mais la forme a changé. On ne parle plus seulement de “bots qui testent des mots de passe” de façon brute, on voit aussi des tentatives plus ciblées, des connexions très fréquentes, parfois même depuis des réseaux d’hébergement qui changent d’adresse IP. Le résultat, pour beaucoup d’administrateurs, ressemble à un bruit permanent : journaux qui gonflent, temps de réponse dégradé, fatigue opérationnelle. Et si vous gérez un site qui doit rester joignable, ce bruit finit par devenir un risque.

Limiter les tentatives de connexion fait partie des mesures les plus rentables, parce que ça réduit la surface d’attaque avec un effort raisonnable. L’objectif n’est pas de “tout bloquer”, c’est de rendre les attaques coûteuses, lentes, et visibles. En pratique, on combine plusieurs leviers, au niveau WordPress, au niveau serveur, et parfois au niveau DNS ou reverse proxy. Selon votre contexte, certaines options seront trop intrusives, d’autres au contraire très efficaces.

Comprendre ce que vous cherchez vraiment à bloquer

Une tentative de connexion ratée n’est pas toutes les erreurs, ni tous les impacts. Il y a plusieurs scénarios qui se ressemblent dans les journaux, mais qui n’ont pas les mêmes conséquences.

Le premier, le plus classique, c’est le brute force de mots de passe. Un bot teste des identifiants connus, parfois en ciblant des utilisateurs “évidents” comme admin ou des variantes. Le deuxième scénario, plus discret, c’est la tentative sur plusieurs adresses d’utilisateurs. Le bot ne se contente pas d’une seule cible, il essaie de faire tomber une session en explorant les comptes. Le troisième, c’est le stuffing de mots de passe, c’est-à-dire l’utilisation de mots de passe déjà compromis ailleurs, souvent en volumes plus “propres”, avec moins d’essais par minute mais plus de chances d’entrer.

Quand vous limitez les tentatives, vous ne limitez pas uniquement les attaques. Vous limitez aussi les erreurs légitimes. C’est là que le jugement compte : un blocage trop agressif peut vous empêcher de vous connecter, ou gêner un équipe entière, notamment si plusieurs personnes partagent le même poste ou si quelqu’un est derrière une IP qui change souvent.

Le bon réglage dépend donc de votre trafic d’administration et de votre manière de gérer l’accès. Si vous avez deux administrateurs, un mot de passe unique, et que vous utilisez un gestionnaire de mots de passe, vos “erreurs” seront rares. Si vous avez une petite équipe, des accès depuis des lieux différents, et un support qui se connecte parfois après changement de mot de passe, vos essais ratés peuvent être plus fréquents, même sans intention malveillante.

Ce que WordPress peut faire directement (et ce que ça ne fait pas)

WordPress propose un socle de sécurité, mais il ne fournit pas, nativement, un mécanisme complet de limitation de taux pour les pages de connexion. Vous pouvez renforcer via des pratiques classiques comme activer un mot de passe fort, éviter les identifiants par défaut, et protéger les comptes. Pourtant, dès que les tentatives deviennent automatisées, vous arrivez vite au point où WordPress seul n’est pas suffisant.

C’est pour ça que, dans la pratique, on s’appuie souvent sur deux familles d’actions :

    des réglages côté application, via plugins ou fonctions de validation, des règles côté serveur, qui attrapent le trafic avant même qu’il n’arrive à WordPress.

Les règles côté serveur ont un avantage psychologique et technique : elles réduisent le travail de PHP, de la base de données, et du stack WordPress, donc elles contribuent aussi à la performance. Elles ont aussi un inconvénient : si vous configurez mal, vous pouvez bloquer des utilisateurs légitimes, ou créer une instabilité difficile à diagnostiquer.

Quand vous cherchez à sécuriser site WordPress, limiter les tentatives est un chantier à traiter comme un “système” et pas comme un bouton. Le plus solide consiste à créer des garde-fous à plusieurs niveaux.

Les leviers les plus efficaces, du plus “simple” au plus “robuste”

1) Limitation via plugin (au niveau WordPress)

Les plugins de sécurité qui gèrent la limitation de tentatives fonctionnent généralement de cette manière : ils comptent les échecs de connexion par adresse IP, parfois par identifiant, et ils bloquent temporairement ou demandent une étape supplémentaire. C’est pratique, parce que vous pouvez régler des seuils, des durées, et parfois des exemptions pour vos propres IP.

Le point délicat, c’est l’IP. Si un utilisateur est derrière un NAT, ou si votre équipe utilise des connexions mobiles, l’adresse IP peut changer. Un blocage par IP devient alors injuste, ou au minimum frustrant. Inversement, si les attaques viennent toutes d’un même bloc d’adresses, l’IP est une excellente cible.

Dans un contexte “entreprise”, j’ai vu une configuration où le seuil de blocage avait été trop bas. Un membre de l’équipe, en voyage, passait par un réseau dont l’IP changeait souvent. Chaque erreur de mot de passe déclenchait un blocage, et l’équipe a fini par désactiver la protection, ce qui a laissé le champ libre aux bots. On a ensuite déplacé l’approche vers un blocage plus long, mais avec une phase de friction plus légère (par exemple un délai progressif avant blocage), et surtout une exemption pour les IP de l’équipe.

2) Limitation côté serveur avec fail2ban ou équivalent

Sur un serveur Linux, fail2ban est souvent la référence pour bannir temporairement des adresses IP en fonction de motifs dans les logs. C’est puissant, parce que ça se fait au niveau du système, et ça peut s’appuyer sur des signatures d’erreurs concrètes, par exemple des 401/403 sur certaines routes, ou des patterns dans les logs web.

Le gros intérêt est que vous réduisez le volume de requêtes qui atteignent WordPress. Les bots passent moins de temps à “casser” le même endpoint. Pour un site qui reçoit déjà beaucoup de tentatives, c’est un gain direct en charge.

Le revers, c’est la maintenance. Les logs changent selon le serveur web (Nginx ou Apache), selon la configuration, et selon le format. Et si vous utilisez un proxy, l’adresse IP réelle peut être cachée derrière celle du proxy, ce qui casse le “qui a tenté quoi” si les en-têtes ne sont pas correctement pris en compte.

image

3) Rate limiting à l’échelle HTTP

Dans Nginx, un reverse proxy, un CDN, ou un load balancer, le rate limiting à l’URL de connexion peut être très efficace. L’idée est d’imposer une limite de requêtes sur une route précise, par adresse IP, ou par session, avec une granularité temporelle.

Ici aussi, la qualité de l’information IP est déterminante. Si votre site est derrière Cloudflare ou un autre service, l’approche dépend de la configuration et de la façon dont le trafic est acheminé. Le rate limiting peut être trop strict et impacter l’écran de connexion lors d’un pic d’utilisateurs légitimes, par exemple lors d’une campagne marketing ou d’un événement où beaucoup de gens se connectent en même temps.

Sur un site à faible volume, le rate limiting “honnête” sur la route wp-login.php et, parfois, les endpoints de l’API d’authentification si vous en avez, fait souvent la différence sans être brutal.

4) Une deuxième barrière : 2FA

Limiter les tentatives aide, mais ce n’est pas une authentification. La deuxième barrière, c’est la 2FA. Avec une authentification à facteur supplémentaire, même si un bot casse un mot de passe (ou réutilise un mot de passe compromis), il ne passe pas sans le second facteur.

Beaucoup d’équipes hésitent parce que le déploiement de la 2FA est un changement d’habitude. Pourtant, du point de vue “incident”, c’est souvent la mesure la plus rassurante. L’attaque ne suffit plus à se transformer en compromission.

La difficulté, ce n’est pas technique uniquement. Il faut penser au scénario de perte de téléphone, aux procédures de récupération, et aux utilisateurs d’urgence. Sans cela, vous transformez une vulnérabilité cyber en vulnérabilité opérationnelle.

Choisir les bons seuils sans vous piéger

La question la plus fréquente que je reçois en audit, c’est : “On met combien de tentatives, et pendant combien de temps ?”. La réponse honnête, c’est qu’il faut calibrer en fonction de vos usages réels.

Si votre site est un blog personnel avec un seul administrateur, vous pouvez vous permettre des seuils stricts. Si votre site est un SaaS avec plusieurs équipes et des accès depuis des environnements variés, vous voudrez quelque chose de moins agressif. Le but n’est pas d’obtenir un score parfait, c’est d’éviter deux types d’incidents : laisser passer des attaques, ou bloquer vos propres accès.

Quelques repères pratiques, sans prétendre à une valeur universelle : beaucoup de réglages “raisonnables” commencent par des fenêtres courtes, puis escaladent progressivement. Par exemple, au lieu de bloquer après 3 essais, vous pouvez imposer un délai, puis un blocage temporaire. Ce genre de mécanisme rend les bots moins efficaces, tout en restant plus tolérant pour un humain qui se trompe une fois, ou qui doit re-taper un mot de passe après une session expirée.

Un autre point souvent oublié : les attaques ne viennent pas uniquement de la page wp-login.php. Il y a aussi des tentatives sur des endpoints annexes, des requêtes vers REST API si des fonctionnalités sont accessibles sans garde adéquate, et des tentatives d’énumération. Limiter une seule route peut améliorer la situation sans éliminer le bruit ailleurs.

Une checklist rapide avant de modifier quoi que ce soit

Avant d’ajuster des blocages, faites une petite préparation pour éviter les surprises. Le bon sens ici, c’est de sécuriser vos accès en parallèle.

    Vérifiez vos méthodes d’accès légitimes, notamment si vous vous connectez depuis plusieurs réseaux ou via un VPN Repérez vos IP administrateur, et assurez-vous que vous pouvez les mettre en exemption dans le système de limitation Testez la procédure de connexion depuis un compte administrateur de manière contrôlée, après chaque changement important Gardez une voie de secours, par exemple une possibilité d’accès au back-office via un canal alternatif ou une procédure de récupération documentée Surveillez les journaux pendant 24 à 48 heures, pour voir si la limitation réduit le bruit ou si elle crée des blocages inattendus

C’est banal, mais dans les faits, c’est là que se joue la réussite. Une limitation “parfaite” sur le papier peut devenir une mauvaise idée si elle coupe votre propre capacité à administrer.

Exemples de politiques de limitation qui marchent bien en pratique

Plutôt que de vous donner une recette unique, je préfère décrire des politiques réalistes, celles que j’ai vues fonctionner dans des environnements comparables.

1) Politique “progressive” : friction d’abord, blocage ensuite

Vous demandez une action supplémentaire ou vous ralentissez après quelques échecs, puis vous bloquez après un seuil plus élevé. Les bots qui testent des listes entières perdent énormément en efficacité, parce qu’ils doivent “payer” chaque échec. Les humains, eux, ont la possibilité de corriger une erreur isolée.

2) Politique “exemption + fenêtre” : stricte pour le reste, souple pour vous

Vous mettez une exemption pour vos plages IP d’administration ou votre poste fixe. Le système reste utile contre les bots, mais ne se trompe pas sur vous. C’est particulièrement utile en environnement bureau, ou si votre équipe se connecte depuis un réseau de confiance.

3) Politique “multi niveaux” : rate limiting web, limitation app, et 2FA

Quand l’attaque est large, il suffit rarement d’un seul mécanisme. Une approche en couches améliore la résilience. Le rate limiting réduit le volume, la limitation WordPress gère ce qui passe quand même, et la 2FA évite la compromission même si une poignée de mots de passe passe.

Le point de vigilance, c’est que les couches peuvent s’additionner. Si vous avez à la fois un rate limit et un plugin de limitation, les seuils peuvent provoquer un comportement cumulatif surprenant. Une connexion qui devrait échouer deux fois avant blocage peut se retrouver stoppée dès la première requête, selon la façon dont chaque composant compte les essais.

Comment éviter l’erreur classique : bloquer “trop” sans s’en rendre compte

Il y a un piège qui revient : vous ajustez la limitation pour contrer une vague d’attaques, tout marche, puis vous oubliez de revenir sur les réglages. Pendant un mois, le site semble calme. Et ensuite, arrive un changement normal de vie, par exemple un membre de l’équipe qui change de poste, une configuration VPN, ou un changement d’opérateur mobile. Tout le monde se met à recevoir des erreurs de connexion, mais le système de sécurité est “vert” et “actif”.

Ce n’est pas une défaillance rare, c’est un effet de bord. Les restrictions par IP se comportent mal quand l’IP change. Les restrictions par compte se comportent mal quand les mots de passe sont réinitialisés. Les restrictions “par navigateur” se comportent mal quand le navigateur change de stockage ou quand le site exige un nouveau jeton.

image

La solution, ce n’est pas de désactiver. C’est de concevoir un modèle qui tolère la vie réelle. En général, cela passe par :

    des seuils assez hauts pour les humains, une escalade progressive plutôt que des blocages immédiats, une capacité de correction rapide quand un compte ou une IP légitime est bloqué.

Limiter aussi l’énumération et la surface d’attaque

Limiter les tentatives de connexion, c’est une brique, mais l’attaque ne se limite pas à “tenter un mot de passe”. Une autre étape fréquente consiste à essayer de savoir si un identifiant existe. WordPress peut renvoyer des messages qui, selon la configuration, donnent des indices. Même si WordPress reste plutôt prudent, des thèmes, des plugins ou des personnalisations peuvent modifier le rendu.

Si vous avez des utilisateurs nombreux ou des comptes “marketing” visibles, le risque d’énumération devient plus concret. Dans ce cas, vous voulez :

    minimiser les indices renvoyés entre un compte existant et inexistant, protéger les endpoints d’authentification et les formulaires associés, limiter les tentatives sur l’ensemble des routes concernées, pas uniquement l’interface wp-login.php.

Là encore, le bon équilibre dépend de votre besoin de diagnostic. En interne, vous voulez des logs riches, en externe, vous ne voulez pas aider l’attaquant à s’orienter.

Où placer vos efforts si vous n’avez pas le temps

Tout le monde n’a pas le luxe de mener un projet complet. Si vous devez prioriser, il y a une logique assez simple. Les mesures “rate limit au plus près” et “2FA” apportent généralement le meilleur rapport effort impact.

Concrètement, si vous ne pouvez faire qu’une seule chose aujourd’hui pour améliorer la sécurité de votre WordPress, je commencerais par limiter la connexion (au niveau serveur ou via un plugin robuste), puis j’activerais la 2FA pour les comptes à privilèges. Le reste, comme le durcissement fin, l’audit des logs, et la rotation des identifiants, vient ensuite.

Voici une comparaison rapide des approches selon votre contexte :

| Approche | Fort quand | Risque principal | Niveau de friction pour vous | |---|---|---|---| | Plugin de limitation WordPress | vous pouvez affiner et exempter des IP | blocage injuste si IP instable, ou cumul avec d’autres règles | faible à moyen | | fail2ban ou règles serveur | trafic bruyant, vous gérez déjà des logs | mauvais parsing des logs, détection IP masquée par proxy | moyen | | rate limiting HTTP sur endpoints | vous avez un reverse proxy ou CDN, trafic stable | seuil trop bas lors de pics https://gardewp.fr/securite-wordpress/ légitimes | faible | | 2FA | vous voulez réduire la gravité d’un mot de passe compromis | perte d’accès sans procédure de récupération | moyen |

Je ne dis pas que les autres mesures ne comptent pas. Je dis juste que, dans beaucoup de projets, cette combinaison réduit à la fois le bruit et le risque.

Cas particuliers : utilisateurs mobiles, équipe, multi-sites

Les règles efficaces pour un site “solo” peuvent être douloureuses pour un environnement plus complexe.

Sur mobile, l’IP peut changer fréquemment. Si vous limitez strictement par IP, les blocages “semblent” aléatoires. Dans un environnement d’équipe, vous pouvez aussi tomber dans un problème de rythme : une personne fait deux erreurs, l’IP est bloquée, et tout le monde derrière la même connexion subit le contrecoup.

Dans un WordPress multisite, la logique se complique encore. Selon la manière dont les administrateurs gèrent les comptes, il peut y avoir des pages d’accès distinctes et des rôles différents. Les plugins de sécurité gèrent parfois multisite de manière variable. Il faut donc tester sur votre configuration exacte, pas sur une hypothèse.

Le point clé reste le même : calibrer pour “la vraie vie” de votre site, pas pour un scénario idéal.

Surveiller sans se perdre

Une limitation de tentatives sans supervision, c’est comme fermer une porte en espérant que le système d’alarme fonctionne. Vous pouvez avoir un gain réel, mais vous pouvez aussi avoir un réglage trop agressif.

La surveillance, ici, doit être pragmatique. Surveillez :

    le volume de requêtes vers wp-login.php et les endpoints liés, les événements de blocage, pour vérifier qu’ils concernent des adresses qui “méritent” d’être bloquées, vos propres tentatives de connexion pendant la période de test.

Si vous constatez que des connexions légitimes échouent plus souvent, vous avez un signe clair. Il faut ajuster les seuils ou ajouter des exemptions.

Une politique de mise en production raisonnable

Quand vous changez la sécurité, il vaut mieux procéder comme pour un changement applicatif, pas comme un “coup de chance”.

Une bonne approche consiste à déployer en fenêtre courte, tester, puis ajuster. Par exemple, vous pouvez d’abord activer une limitation moins agressive, observer le comportement, puis durcir si le bruit reste élevé. Cette méthode évite de vous retrouver coincé dès la première version.

Je recommande aussi de documenter ce que vous changez. Pas besoin d’un dossier encyclopédique, mais une note interne avec la date, le seuil, la logique de blocage, et la liste des exemptions utiles. En cas de souci, vous gagnerez des heures.

Ce que j’éviterais presque toujours

Il y a quelques gestes qui reviennent comme des “solutions rapides” mais qui posent souvent plus de problèmes qu’ils n’en résolvent.

Le premier, c’est de bloquer de manière trop stricte sans exemption claire. Le deuxième, c’est de multiplier les plugins de limitation sans comprendre leurs interactions. Deux mécanismes qui comptent différemment peuvent produire un résultat incohérent : vous pensez avoir autorisé trois tentatives, mais l’un des composants en compte une seule requête comme un échec sévère.

Le troisième, c’est de remplacer la sécurité par l’obscurité. Changer l’URL de connexion peut réduire le bruit, mais ce n’est pas une stratégie complète. Les attaques se déplacent, et la “vraie sécurité” reste la réduction de la surface et la friction contrôlée.

Enfin, le quatrième, c’est l’absence de plan de récupération pour la 2FA. Si vous activez une deuxième barrière, vous devez avoir une procédure de récupération planifiée. Sinon, vous risquez de vous pénaliser au moment où il ne faut pas.

Réglage final : une décision à prendre selon votre tolérance à la friction

Limiter les tentatives de connexion, c’est toujours un compromis. Si vous rendez la protection trop stricte, vous augmentez le risque d’auto-bloquage. Si vous la rendez trop souple, vous laissez du travail aux bots et vous conservez le bruit.

image

Mon critère de décision est simple : “Est-ce que je peux récupérer dans un délai court si quelque chose se passe mal ?”. Si la réponse est oui, vous pouvez aller plus loin dans la limitation. Si la réponse est non, vous commencez par sécuriser la récupération, par exemple avec des exemptions ciblées et un canal d’accès de secours, puis vous augmentez progressivement.

Pour la plupart des sites, la trajectoire la plus saine ressemble à ceci : limitation raisonnable et progressive, exemptions pour les accès légitimes, surveillance sur 48 heures, puis renforcement si nécessaire. Et en parallèle, une 2FA sur les comptes à privilèges pour que la menace ne se transforme pas en incident majeur.

Si votre objectif est de sécuriser site WordPress de façon durable, c’est ce mélange qui tient. Vous réduisez les tentatives, vous gagnez en performance opérationnelle, et vous diminuez la gravité d’une compromission potentielle. Les bots peuvent toujours essayer, mais ils deviennent incapables de faire le travail rapidement, et surtout, ils ne peuvent pas passer les barrières sans que vous le constatiez.