Sécurité WordPress : protéger les pages de connexion par rate limiting

Les tentatives de connexion contre un site WordPress viennent rarement au hasard. Elles suivent des rythmes, des schémas, et surtout une recherche persistante de comptes valides. Le formulaire de connexion à wp-login.php et, par extension, l’accès à wp-admin, finissent souvent en cible principale. Quand la machine qui attaque peut multiplier les essais sans pause, elle gagne du temps. C’est là que le rate limiting change la donne: au lieu de laisser chaque requête s’empiler, on impose une cadence, on réduit la surface de brute force, et on évite que votre serveur passe son temps à répondre à des tentatives vouées à échouer.

Le rate limiting n’est pas une solution magique. Il ne “verrouille” pas à lui seul les identifiants et ne remplace pas une bonne hygiène (mots de passe solides, limitation des comptes admin, 2FA, mises à jour). Mais, appliqué au bon endroit et avec des paramètres réalistes, il devient un verrouage discret, efficace, et souvent plus sain pour la charge serveur qu’un blocage agressif.

image

Pourquoi la connexion WordPress souffre particulièrement

Un WordPress exposé publiquement renvoie des signaux assez constants. Le chemin wp-login.php existe presque partout, les endpoints d’administration sont prévisibles, et les tentatives automatiques reviennent en boucle. Une campagne de brute force ou de credential stuffing peut générer des milliers de requêtes sur une fenêtre courte. Ensuite, il reste l’autre problème, plus sournois: même si l’attaquant n’obtient jamais de succès, chaque tentative mobilise des ressources côté serveur (traitement PHP, requêtes base de données, vérifications de session, logs, génération de réponses).

Sur un site déjà chargé, ou avec un hébergement partagé, ce bruit peut avoir des effets secondaires. Le trafic “attaque” peut devenir une part non négligeable du trafic total. Résultat: latence, erreurs 5xx, et parfois des blocages applicatifs qui finissent par toucher aussi des utilisateurs légitimes. Un rate limiting bien réglé n’empêche pas les vrais utilisateurs de se connecter, il leur donne même une expérience plus stable, parce que le serveur respire.

Un point souvent mal compris: le but n’est pas de stopper chaque requête. Le but est de faire en sorte que les requêtes “coûtent” du temps à l’attaquant. Si une machine doit ralentir, elle met plus longtemps à tenter toutes les combinaisons, donc elle a moins de chances de retenter des milliers d’essais dans la même heure.

Comprendre le rate limiting, sans le confondre avec un blocage

Le rate limiting consiste à limiter le nombre de requêtes autorisées dans une fenêtre de temps. Par exemple, “10 tentatives par minute par IP” est une règle simple. Selon la technologie, le comportement peut varier:

    soit on renvoie directement une erreur (souvent 429 Too Many Requests), soit on ralentit (plus rare), soit on applique un contrôle plus fin (par endpoint, par chemin, parfois par identifiants de formulaire).

Le blocage, lui, est plus binaire: “cette IP est bannie pendant X minutes”. Un bannissement long peut être efficace, mais il augmente le risque de faux positifs, notamment pour des utilisateurs derrière des réseaux partagés, des NAT d’entreprise, ou des services de proxy.

Le rate limiting est souvent plus “souple”. Il peut freiner sans tomber dans le bannissement total. C’est aussi pour cela qu’il s’intègre bien avec d’autres mécanismes: challenge (captcha), détection de bots, et protection applicative.

Où appliquer la règle pour que ça serve vraiment

Sur WordPress, il ne suffit pas de limiter “tout le site”. Limiter toute une infrastructure peut provoquer des blocages incompréhensibles, surtout pour des assets, des API ou des pages dynamiques. Le bon réflexe consiste à cibler les points d’entrée de connexion.

Concrètement, vous voulez couvrir:

    la page de connexion: wp-login.php l’accès à wp-admin (car certains flux tentent directement des actions d’admin) les endpoints liés à l’authentification qui existent encore dans beaucoup d’installations, notamment XML-RPC (selon votre usage)

Ensuite, vous choisissez le “scope” du rate limiting. L’approche par IP est la plus répandue, mais elle n’est pas parfaite. Des utilisateurs légitimes peuvent partager une même IP via un NAT. À l’inverse, des attaquants peuvent changer d’IP et échapper à une règle uniquement IP. C’est pour cela qu’on parle de combinaison de protections: rate limiting, puis d’autres signaux (mots de passe échoués, empreintes de comportement, réputation d’adresse IP, challenge).

Les bonnes briques côté reverse proxy et WAF

La façon la plus fiable d’implémenter le rate limiting dépend de votre architecture. Beaucoup de sites ont un reverse proxy devant WordPress, par exemple Nginx, Apache, ou un service type WAF/CDN. Dans ces cas, vous pouvez appliquer la règle avant d’atteindre PHP. Ça réduit la charge applicative et évite que votre base de données se fasse marteler.

Si vous utilisez un CDN/WAF, cherchez des paramètres de “rate limiting” ou “bot protection”. L’avantage est la simplicité: règle configurée, logs, et souvent une intégration directe avec d’autres contrôles. L’inconvénient, ce sont parfois des limites de granularité. Par exemple, certains services limitent “par URL” de manière assez basique, ou imposent une politique globale sur des endpoints.

Si vous gérez Nginx vous-même, vous pouvez coder une règle par chemin. L’idée reste simple: une zone de limitation, une clé (souvent $binary remoteaddr), un nombre et une fenêtre.

Sur Apache, ce sera souvent via des modules comme mod ratelimit ou une couche de modsecurity, mais selon votre stack, ce n’est pas toujours aussi direct.

Enfin, dans beaucoup d’environnements, vous pouvez combiner le rate limiting WAF avec Fail2ban (ou un équivalent) pour bannir plus agressivement les comportements persistants, tout en gardant une règle de base plus “souple”.

Rate limiting au niveau serveur: Nginx, Apache, et cohérence des logs

Un détail pratique fait gagner du temps: assurez-vous que les journaux vous permettent d’identifier rapidement l’impact. Si la règle renvoie 429, vous devez le voir dans vos logs web. Si elle fait autre chose (par exemple redirection vers une page d’erreur custom), vérifiez ce que l’application reçoit réellement.

En environnement Nginx, la cohérence vient souvent du fait que la limitation se fait au niveau HTTP, avant toute exécution PHP. C’est utile parce que wp-login.php déclenche déjà une série de traitements applicatifs, même si l’identifiant est faux. En stoppant avant, vous économisez.

Avec Apache, l’ordre des modules peut compter. Une règle peut ne s’appliquer qu’après certaines transformations. Et certaines configs d’hébergement n’exposent pas facilement la personnalisation.

Un autre piège: ne limitez pas seulement le chemin “wp-login.php”, si votre site utilise des variantes. Certains bots ciblent wp-admin, d’autres appellent wp-login.php avec des paramètres. Les règles basées uniquement sur “exact path” peuvent rater une partie des requêtes si votre configuration est trop stricte. Inversement, une règle trop large peut toucher des utilisateurs légitimes qui accèdent à des ressources liées à l’administration, ou des scripts de maintenance.

Paramétrer un rate limit réaliste: chiffres, fenêtres, et effets de bord

Les chiffres ne sont pas universels, surtout quand on parle de rate limiting. Il faut tenir compte du volume réel de connexions. Un site qui reçoit peu de connexions peut accepter une règle plus tolérante. Un site avec une communauté active, une équipe support, ou un flux régulier d’utilisateurs qui se connectent depuis des réseaux partagés, demande une règle moins brutale.

Dans la pratique, on voit souvent des ordres de grandeur comme:

    5 à 10 tentatives par minute par IP pour l’endpoint de connexion une règle plus permissive sur wp-admin si votre équipe utilise beaucoup de navigation d’administration une durée d’observation qui évite de punir une “série d’essais” causée par un utilisateur qui a juste oublié son mot de passe (et qui retente)

Le point subtil: si vous fixez trop bas, vous risquez de provoquer un blocage lors d’erreurs répétées légitimes. Une personne qui tape un mot de passe oublié, se trompe, puis retente, peut déclencher le rate limit. Elle ne sera pas “bloquée définitivement”, mais elle devra attendre. Sur un site d’entreprise, ce délai se ressent. Sur un site e-commerce, ça peut générer des tickets support.

Autre cas: l’authentification à deux facteurs. Certaines tentatives passent, d’autres échouent, mais le comportement côté HTTP peut ressembler à “des tentatives”. Il faut tester après activation de 2FA, car le flux peut ajouter des requêtes supplémentaires autour de l’authentification.

Enfin, il faut regarder le trafic provenant de l’extérieur. Les attaquants changent parfois d’IP. Une règle “par IP” seule peut donc être contournée, mais elle ralentit quand même, et elle réduit drastiquement les tentatives depuis des IP stables. C’est rarement inutile.

Deux stratégies qui marchent souvent: limiter en entrée et renforcer en sortie

J’aime raisonner en deux étages.

Premier étage: un garde-fou simple sur l’endpoint de login, au niveau reverse proxy ou WAF. Ce garde-fou a un objectif clair, limiter le rythme brut des requêtes.

Deuxième étage: un renforcement côté application. Il peut s’agir d’un plugin de sécurité qui ajoute des contrôles sur l’échec de connexion, qui modifie le comportement quand plusieurs mots de passe échouent, ou qui déclenche un challenge.

Le compromis est important: si vous mettez un mécanisme côté application qui détecte trop finement, il peut être plus coûteux. À l’inverse, si vous mettez tout au niveau reverse proxy, vous risquez de moins bien distinguer les cas, car vous ne voyez pas l’état applicatif.

Dans WordPress, beaucoup d’attaques “semblent” au niveau HTTP comme des échecs de formulaire. Donc, même au premier étage, un bon ciblage par endpoint apporte déjà un gain significatif.

Exemples de politiques de rate limiting (et ce qu’elles impliquent)

Voici deux politiques fréquentes, à adapter selon votre trafic.

Politique A, frugale et efficace sur wp-login.php

Vous limitez fortement l’endpoint wp-login.php. Les requêtes vers ce chemin déclenchent une règle par minute. Les faux positifs arrivent surtout quand un utilisateur retente trop vite après un mot de passe oublié, ou quand un client est instable sur réseau.

Politique B, plus douce sur wp-admin, plus stricte sur wp-login.php

Vous mettez une règle assez sévère sur wp-login.php, et une règle plus permissive sur wp-admin. Le but est d’éviter que des accès légitimes à l’interface d’administration (navigation, chargement de ressources) soient perturbés. Sur certains sites, wp-admin est aussi la cible d’URL probes. Une règle douce permet de réduire ce bruit tout en laissant respirer le reste.

Il y a un troisième cas, plus niche: certaines personnes ciblent aussi xmlrpc.php. Si vous n’utilisez pas XML-RPC, la question devient moins un rate limit et plus une réduction de surface (désactivation). Si vous l’utilisez, vous pouvez appliquer une limitation spécifique, mais testez, car certains clients légitimes utilisent XML-RPC au rythme attendu par leur implémentation.

Une petite check-list avant de toucher aux règles

Avant de déployer, je recommande de faire un diagnostic rapide. Ça évite de “casser” la connexion légitime, ce qui est l’ennemi numéro un.

    Vérifiez le chemin exact utilisé pour la connexion sur votre site, notamment si vous avez modifié le slug de connexion ou installé des plugins qui changent le flux. Testez depuis une IP “proche de la réalité” (réseau bureau, mobile, VPN si votre équipe en utilise). Surveillez les logs de connexion et les erreurs HTTP (429, 403, erreurs applicatives) pendant 1 à 2 jours après activation. Si vous utilisez 2FA, validez le comportement complet, y compris les échecs. Gardez une règle de secours pour votre propre IP de maintenance, afin de pouvoir accéder même en cas de paramètre trop strict.

C’est une liste courte, mais elle évite les corrections en urgence. Le problème, ce n’est pas le rate limiting. C’est le déploiement sans validation.

Comment choisir les paramètres: clé, fenêtre, seuil

Le choix de la clé de limitation dépend de ce que vous voulez protéger.

    Clé par IP: simple, efficace contre les attaques “fixes”, moins efficace contre la rotation d’adresses. Clé par session ou cookie: mieux pour distinguer utilisateurs, mais moins disponible si la requête n’est pas “authentifiée” et que les bots n’ont pas de session stable. Clé par endpoint et paramètres: utile pour wp-login.php, car vous pouvez cibler les tentatives de login sans impacter d’autres routes.

Ensuite, la fenêtre de temps. Les fenêtres trop courtes peuvent laisser passer des attaques espacées. Les fenêtres trop longues rendent le rate limit trop pénalisant pour les utilisateurs légitimes. La bonne fenêtre dépend de la cadence réelle de votre trafic de connexion.

En général, une minute est un bon premier repère. Beaucoup de systèmes utilisent ce genre d’ordre de grandeur. Une alternative est de combiner une limite “par minute” et une limite “par heure” pour gérer la persistance. Ainsi, une personne qui retente dix fois dans l’heure ne serait pas pénalisée de la même façon qu’un bot qui en fait cent dans la même heure.

Enfin, le seuil. Commencez souvent modérément, observez, ajustez. Un seuil trop bas peut transformer “un rappel de mot de passe raté” en blocage temporaire. Un seuil trop haut peut réduire l’impact sur les bots. L’objectif est d’être assez bas pour faire une différence, assez haut pour ne pas gêner la majorité des utilisateurs.

image

Exemple de paramètres raisonnables à partir d’un besoin typique

Voici un cadre de travail, sans prétendre qu’il est universel. L’idée est de vous donner des points de départ que vous affinerez avec vos logs.

    wp-login.php: 5 à 10 requêtes par minute par IP wp-admin: 20 à 60 requêtes par minute par IP, selon le niveau de visite d’administration si XML-RPC est exposé: 5 à 10 requêtes par minute par IP (ou désactivation si vous n’en avez pas besoin) fenêtre d’observation plus longue: ajouter une limite “par heure” si vous voyez des attaques qui étalent leurs tentatives

Si votre site est très petit, vous pouvez parfois être plus strict. Si vous avez des équipes support qui se connectent depuis des réseaux partagés, vous devrez être plus prudent.

Plugins WordPress: ce qu’ils font réellement, et pourquoi ça peut être complémentaire

Beaucoup de plugins de sécurité proposent du rate limiting et de la protection contre la brute force. Leur valeur tient à ce qu’ils sont “au courant” de WordPress. Ils peuvent, par exemple, suivre les échecs de connexion sur wp-login.php, ou appliquer des mesures supplémentaires quand un identifiant tente plusieurs mots de passe.

Mais il y a une réalité: tout ce qui se fait côté application ne réduit pas autant la charge que ce qui se fait avant PHP. Un bot qui tape mille fois peut quand même déclencher mille exécutions PHP si la limitation n’intervient pas à l’entrée. C’est pour cela que, quand c’est possible, je préfère un contrôle au niveau reverse proxy ou WAF en premier, puis une couche applicative ensuite.

Autre détail: certains plugins modifient le comportement du login, ajoutent des captchas, ou changent des règles. Si vous avez déjà des règles côté serveur, le risque est de “doubler” trop fort et de créer une friction excessive.

Mon conseil pratique: choisissez votre source principale de rate limiting. Si vous avez un WAF, prenez-le comme base. Si vous n’en avez pas, un plugin peut être le moyen le plus rapide. Dans tous les cas, testez sur une session réelle, puis observez sur plusieurs heures.

Vérifier l’impact: mesurer avant de juger

Le meilleur test, ce n’est pas un test “à vide”. C’est une mesure pendant une période où vous aurez encore des tentatives légitimes.

Regardez:

    le nombre de requêtes vers wp-login.php la proportion de réponses 429 ou autre codes renvoyés la latence globale du site les plaintes internes ou, plus simplement, le nombre de connexions ratées après déploiement

Si vous êtes capable de voir aussi les “User-Agent” et les chemins exacts, vous aurez une confirmation du ciblage. Les requêtes de bots ont souvent des patterns répétitifs. Vous voulez être sûr que votre règle ne touche pas des clients légitimes (par exemple une IP de maintenance, un outil interne, un moniteur).

Un cas d’edge que j’ai déjà rencontré: une règle trop stricte peut impacter un outil de vérification de connexion utilisé par une équipe. Par exemple, un script qui vérifie la page de connexion toutes les 10 secondes, ou un test qui simule un accès à wp-admin. Dans ce cas, vous voyez vite des 429 dans les logs, mais pas forcément une plainte utilisateur. Le “client légitime” est l’outil.

Réduire encore la surface: pas seulement le rate limiting

Le rate limiting protège la connexion, mais vous pouvez réduire la surface globale pour que le besoin soit moins important. Sans tomber dans la complexité, quelques actions changent souvent la donne:

    limiter les comptes admin exposés et réduire leur nombre activer 2FA pour les comptes à privilèges utiliser des mots de passe longs et uniques garder WordPress, thèmes et extensions à jour surveiller les tentatives et les logs de sécurité

Je le dis sans moraliser: un bon rate limiting ne compense pas des mots de passe faibles ou des plugins obsolètes. En revanche, il limite les dégâts quand quelque chose n’est pas parfait.

Ajuster au fil du temps: quand les règles doivent évoluer

Une règle de rate limiting n’est pas “faite pour toujours”. Votre trafic change, vos utilisateurs changent, et les attaquants ajustent aussi leur manière d’agir. Si vous voyez que les 429 augmentent mais que les plaintes restent stables, vous êtes probablement sur la bonne voie. Si vous voyez des blocages côté utilisateurs, ajustez à la hausse le seuil ou la fenêtre pour les connexions.

Parfois, vous devez aussi raffiner le ciblage. Si des attaques passent par wp-admin et pas uniquement par wp-login.php, il faut étendre la protection au bon endpoint, ou vérifier qu’une redirection ne déroute pas la requête vers une autre route.

Dernier point, souvent oublié: les règles s’appuient sur des mécanismes d’IP. Si votre infrastructure inclut un load balancer ou un proxy, assurez-vous que vous utilisez la bonne adresse IP dans la clé de limitation. Sinon, toutes les requêtes peuvent être “ramenées” à l’IP du proxy, ce qui rend le rate limiting moins efficace ou au contraire trop punitif.

Mettre en place sans risque: un déploiement progressif

Si vous devez déployer sur un site en production, évitez l’approche “on règle une fois et on prie”. Faites plutôt un déploiement progressif, même simple.

Vous pouvez:

    commencer sur un seuil plus tolérant surveiller les logs pendant 24 heures durcir par étapes si les faux positifs restent faibles garder une exception pour vos IP de maintenance

Si votre hébergement permet un mode “log-only” (parfois proposé par des WAF), testez d’abord en observant ce que la règle aurait bloqué. C’est utile pour calibrer sans interrompre la connexion.

Paramètres de secours: garder l’accès à votre compte

Quand on touche à la sécurité, le risque d’erreur n’est pas théorique. Une mauvaise clé, une fenêtre mal choisie, ou une règle qui s’applique trop largement, et vous pouvez vous retrouver bloqué lors d’une intervention.

Pour éviter le scénario pénible, gardez une stratégie d’accès de secours. Cela peut être une exception explicite pour votre IP, une règle temporaire de contournement, ou une procédure d’accès via une console d’hébergement. L’idée est la même: vous devez pouvoir administrer le site même si la règle se révèle trop stricte.

Si vous travaillez en équipe, c’est aussi utile de définir une procédure claire. Qui a le droit de modifier la règle? Qui valide les logs? À quel moment on ajuste?

À quoi ressemble un bon résultat après activation

Un bon déploiement, c’est quand vous constatez une baisse nette des tentatives “brutes” sur wp-login.php, avec un minimum d’impact sur les connexions légitimes. Vos logs montrent des 429 sur des patterns de bots, mais vos utilisateurs continuent à se connecter sans devoir attendre des durées disproportionnées.

image

Vous pouvez aussi voir des changements dans la qualité des tentatives. Certains bots abandonnent quand ils rencontrent trop de friction, d’autres changent de stratégie. Dans tous les cas, le rate limiting vous apporte une amélioration immédiate, parce que l’attaquant ne peut plus marteler à un rythme identique.

Le vrai signe de réussite, c’est souvent une diminution de la charge et une stabilité accrue du site. La sécurité se mesure aussi dans la capacité de votre serveur à répondre normalement, quand le reste du trafic devient bruyant.

En pratique, quelle approche choisir pour votre WordPress

Le choix dépend de votre environnement. Si vous êtes derrière https://gardewp.fr/securite-wordpress/ un WAF ou un reverse proxy géré, c’est souvent la voie la plus efficace. Si vous gérez Nginx ou Apache, vous pouvez faire un ciblage par chemin. Si vous voulez avancer vite sans toucher à l’infra, un plugin côté WordPress peut aider, mais je recommande de ne pas se limiter à cela si votre trafic cible et votre exposition sont élevés.

Et surtout, ne cherchez pas à tout verrouiller en une seule règle. Le rate limiting est puissant quand il est cohérent avec le reste: 2FA, mots de passe solides, mises à jour, et surveillance. Quand vous assemblez ces pièces, vous obtenez un mécanisme qui n’est pas seulement “agressif”, il est réaliste.

Une dernière remarque, liée à votre objectif “renforcer sécurité WordPress”: le rate limiting est un excellent levier parce qu’il traite un problème concret, les tentatives répétées, sans exiger de changer votre logiciel. Vous gagnez du temps et de la résilience, puis vous ajustez progressivement selon vos logs.

Si vous me décrivez votre configuration (Nginx ou Apache, présence d’un WAF/CDN, et si vous utilisez XML-RPC), je peux proposer des plages de paramètres plus précises et des endroits exacts où appliquer la règle, tout en minimisant le risque de faux positifs.