Le fichier wp-login.php de notre site a reçu 4 658 requêtes hostiles en 31 jours, envoyées depuis 380 adresses IP différentes, et pas une seule n’a atteint le formulaire de connexion de WordPress. Ce ne sont pas des estimations de fournisseur de sécurité : ce sont les journaux d’accès bruts de wpadminlab.com, du 12 août au 11 septembre 2026, que j’ai dépouillés ligne par ligne. Si vous administrez un WordPress ordinaire, sans notoriété particulière, voici ce qui frappe à votre porte, et surtout ce qui l’arrête vraiment.

Les chiffres bruts, avant toute recommandation
Le site tourne sur un hébergement mutualisé o2switch, avec LiteSpeed devant Apache. J’ai analysé les journaux d’accès archivés (août et septembre) plus le journal courant, soit 184 749 requêtes sur 31 jours. Sur ce total, 18 094 requêtes relèvent d’une activité hostile identifiable, soit 9,8 % du trafic, 584 par jour en moyenne. Pour donner l’échelle, sur la même période les visiteurs humains ont généré environ 19 669 pages vues : le site encaisse presque une requête d’attaque par page réellement lue.
| Cible | Requêtes | IP distinctes | Ce qui s’est passé |
|---|---|---|---|
wp-login.php |
4 658 (4 059 GET, 599 POST) | 380 | 4 408 réponses 302, 200 réponses 404, 50 réponses 301. Zéro réponse 200. |
| Sondes de fichiers sensibles | 13 158 | 639 | .env et ses variantes en tête, puis /wp-admin/install.php, /.git/config, wp-config.php.bak. |
xmlrpc.php |
204 (92 GET, 112 POST) | 154 | Fichier désactivé : 100 % de 301 ou 404. |
Recherche de webshell dans uploads |
45 | quelques unes | Fichiers du type uploads/2026/222.php, tous en 404. |
Énumération d’auteurs (?author=, REST users) |
29 | 15 | 301 vers la home et 404 sur la route REST. |
Le point qui compte le plus dans ce tableau tient en deux nombres : 380 adresses IP, dont 213 n’ont envoyé qu’une seule requête et 238 en ont envoyé trois au maximum. Une seule adresse a insisté 317 fois. Autrement dit, l’attaque type sur wp-login.php n’est pas une machine qui martèle, c’est un réseau qui distribue. Tout ce qui compte les échecs par adresse IP part avec un temps de retard.
À quoi ressemble une rafale dans le journal
Le 12 août, 279 POST ont été envoyés sur wp-login.php en une seule journée. L’extrait ci-dessous en montre 14, en dix secondes, à 15 h 33, depuis le bloc d’adresses 155.248.242.x. Chaque requête porte un user-agent différent, macOS, Linux, Windows, Chrome, Safari, Firefox, pour ressembler à des humains distincts. Le référent est toujours la page de connexion elle-même, comme le ferait un navigateur qui vient de soumettre le formulaire. Le seul détail qui trahit la machine, c’est le rythme.

On retrouve le même schéma le 17 août (162 POST), le 25 août (44) et le 1er septembre (70), cette fois avec une rotation d’adresses toutes les deux ou trois tentatives : 74.244.163.x, puis 154.47.150.x, puis 186.52.139.x, à une minute d’intervalle. C’est exactement le comportement qui avait contourné notre limiteur de connexion par adresse IP fin juillet et abouti à la compromission du site que nous avons documentée. Les heures de pointe sont aussi parlantes : le créneau 12 h à 14 h, heure de Paris, concentre à lui seul 1 730 requêtes sur wp-login.php sur le mois. Les botnets travaillent aux heures de bureau, probablement parce que leurs opérateurs aussi.
La preuve que rien n’atteint WordPress
Depuis le 29 juillet, wp-login.php est placé derrière une authentification HTTP Basic gérée par Apache, en amont de WordPress. Voici ce que renvoie réellement une tentative de connexion envoyée sans ce premier mot de passe, telle que je l’ai lancée aujourd’hui depuis notre VPS :
$ curl -s -o /dev/null -D - -X POST https://wpadminlab.com/wp-login.php
--data 'log=admin&pwd=admin123&wp-submit=Se+connecter'
HTTP/2 302
date: Fri, 11 Sep 2026 13:39:49 GMT
location: https://wpadminlab.com/wp-login.php
www-authenticate: Basic realm="WP Admin Lab - Acces restreint"
x-redirect-by: WordPress
server: o2switch-PowerBoost-v3
Le serveur répond 302 avec un en-tête WWW-Authenticate. Le corps fait zéro octet, aucun cookie WordPress n’est posé, le mot de passe envoyé n’est jamais comparé à quoi que ce soit. Particularité de LiteSpeed chez o2switch : il renvoie un 302 plutôt qu’un 401 franc, ce qui explique les 4 408 lignes en 302 dans le tableau. Cela déroute d’ailleurs certains outils d’attaque, qui interprètent une redirection comme un succès de connexion et repartent tester les cookies.
Sur nos 4 658 requêtes du mois, aucune n’a obtenu de réponse 200 sur wp-login.php. Les 200 réponses 404 et les 50 réponses 301 sont d’autres formes de rejet, variantes de chemin comme //wp-login.php ou réponse du gate lui-même selon le client : là non plus, aucune n’a atteint le formulaire. Le gate absorbe donc la totalité du volume, et WordPress ne voit même pas passer la tentative. C’est la différence fondamentale avec une extension de sécurité : une extension s’exécute après le chargement de WordPress, elle consomme du PHP et de la base de données pour chaque essai, et elle ne peut bloquer que ce qu’elle a déjà laissé entrer.
Le reste du bruit : .env, xmlrpc et énumération
La deuxième courbe du graphique est la plus volumineuse et elle n’a rien de spécifique à WordPress. Sur 13 158 sondes, plus de 2 900 visent un fichier .env ou l’une de ses variantes (.env.bak, .env.production, /api/.env, une trentaine de déclinaisons). Le scanner ne sait pas que vous êtes sous WordPress, il cherche des secrets Laravel ou Node laissés à la racine. Juste derrière : 414 appels à /wp-admin/install.php, qui cherchent une installation jamais terminée, 236 requêtes vers /.git/config et /.git/HEAD, 62 vers wp-config.php.bak et 57 vers /.aws/credentials. Le pic du 21 août atteint 1 513 sondes en une seule journée, le rythme typique d’un scanner qui déroule sa liste de chemins d’un trait.
xmlrpc.php reste sollicité, 204 fois, mais il est désactivé ici depuis longtemps et tout finit en 404. Un détail m’a amusé : 44 requêtes arrivent avec le user-agent WordPress/5.0; https://wpadminlab.com, autrement dit un bot qui se fait passer pour notre propre site pour tenter un pingback. Enfin, l’énumération d’auteurs a été tentée 29 fois seulement, par 15 adresses : ?author=1 redirige vers l’accueil et la route /wp-json/wp/v2/users renvoie 404 pour les visiteurs anonymes. Cette dernière route mérite d’être fermée chez vous aussi, elle expose l’identifiant de connexion en clair sur une installation par défaut.
Ce que je recommande, dans cet ordre
- Un mot de passe HTTP devant wp-login.php. Une directive
AuthType Basicdans le.htaccess, un fichier.htpasswdhors du dossier web, et c’est réglé. Sur un mois, cela a bloqué 100 % des tentatives avec zéro cycle PHP. Si votre hébergeur autorise l’allowlist d’adresses IP et que votre équipe travaille depuis des adresses fixes, une directiveRequire ipfait le même travail sans mot de passe supplémentaire. Le guide de connexion à wp-admin détaille le parcours utilisateur qui en résulte. - Désactiver xmlrpc.php si aucune application mobile ni Jetpack n’en dépend. C’est un point d’entrée qui accepte des centaines de couples identifiant et mot de passe en une seule requête grâce à
system.multicall, donc un limiteur par requête n’y voit rien. - Fermer l’énumération : redirection de
?author=et route RESTusersréservée aux utilisateurs connectés. Cela coûte une dizaine de lignes dansfunctions.phpet retire aux bots la moitié du travail, l’identifiant. - Ne rien laisser traîner à la racine. Les sondes
.env,.gitetwp-config.php.bakne trouvent quelque chose que si vous avez laissé quelque chose. Sauvegardes, exports SQL, dépôts Git clonés danspublic_html: tout cela doit vivre hors du dossier web. Notre scanner WordPress en ligne teste justement une trentaine de ces chemins sur votre site. - Un limiteur de connexion, mais en dernier. Il garde son utilité contre le script naïf qui martèle depuis une adresse, et il journalise les échecs, ce qui est précieux. Il ne doit simplement jamais être votre première ligne.
Changer l’URL de connexion, ce que nous expliquons dans le guide pour changer l’URL de wp-admin sans plugin, réduit le bruit mais ne protège pas : un scanner qui suit le lien « Connexion » ou lit le HTML d’une page de commentaire retrouve la nouvelle adresse en une requête. Je le considère comme un confort pour les journaux, pas comme une mesure de sécurité.
Ce que je ne recommande plus
Je ne recommande plus une extension de limitation de tentatives comme réponse principale au brute force. Le chiffre de ce mois est sans appel : 238 adresses sur 380 se sont arrêtées avant la troisième tentative, donc sous le seuil de blocage de la plupart de ces extensions, et elles ont été relayées par d’autres. Cette approche a été conçue pour l’attaquant de 2012, celui qui essayait 10 000 mots de passe depuis un serveur loué. Le brute force de 2026 est distribué, lent par adresse, rapide au total, et il vise d’abord les mots de passe réutilisés plutôt que les mots de passe faibles.
Je me méfie aussi des tableaux de bord qui affichent « 12 000 attaques bloquées cette semaine ». Le chiffre est probablement vrai, mais il mélange les sondes .env qui ne concernaient pas WordPress, les GET de reconnaissance sur wp-login.php et les vrais POST. Sur notre mois, les vrais essais de mot de passe représentent 599 requêtes, soit 3 % de l’activité hostile totale. Le reste est du bruit qu’un serveur correctement configuré absorbe en 404 sans y penser. Compter le bruit sert à vendre la protection, pas à la choisir. Pour la méthode générale, notre guide pour protéger WordPress contre le brute force reste valable, mais lisez-le avec cette hiérarchie en tête.
Reproduire le comptage chez vous
Sur cPanel, les journaux bruts vivent dans ~/access-logs/ pour le jour courant et dans ~/logs/ pour les archives mensuelles compressées, à condition d’avoir activé l’archivage dans « Raw Access ». Trois commandes suffisent pour obtenir l’essentiel de ce que j’ai mesuré :
# Nombre de POST sur wp-login.php dans l'archive du mois
zcat ~/logs/votre-domaine-ssl_log-Sep-2026.gz | grep -c '"POST /wp-login.php'
# Adresses distinctes qui ont touché wp-login.php, et combien de fois chacune
zcat ~/logs/votre-domaine-ssl_log-Sep-2026.gz | grep 'wp-login.php' | awk '{print $1}' | sort | uniq -c | sort -rn | head
# Les vingt chemins sensibles les plus sondés
zcat ~/logs/votre-domaine-ssl_log-Sep-2026.gz | grep -E '.env|.git/|wp-config|install.php|.bak' | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
Regardez d’abord la colonne des statuts. Si vous voyez des 200 sur les POST de wp-login.php, chaque tentative est arrivée jusqu’à WordPress et a été évaluée par PHP. Si vous voyez des 302 avec un en-tête d’authentification, ou des 401, l’essai s’est arrêté au serveur web. C’est ce statut, et pas le nombre d’attaques, qui dit si votre protection fonctionne.
Dernier chiffre de la série, hors sujet mais difficile à ignorer : sur le même mois, GPTBot a demandé 3 211 pages, AhrefsBot 3 028, SemrushBot 2 620, ClaudeBot 1 835, et Googlebot seulement 1 765. Les robots d’IA et d’outils SEO lisent aujourd’hui ce site deux fois plus que le moteur qui lui envoie ses visiteurs. Ce sera le sujet d’un prochain dépouillement.
FAQ sur wp-login.php
Est-ce normal de voir autant de requêtes sur wp-login.php dans mes logs ?
Oui. Un site sans aucune notoriété reçoit ici 150 requêtes par jour en moyenne sur cette page, avec des pointes à 759. Ce volume ne signifie pas que vous êtes ciblé personnellement, il signifie que votre domaine figure dans les listes que les botnets parcourent.
Le statut 302 sur wp-login.php veut-il dire qu’une connexion a réussi ?
Pas forcément. Une connexion réussie renvoie bien un 302 vers wp-admin, mais un gate HTTP Basic derrière LiteSpeed renvoie aussi un 302 accompagné d’un en-tête WWW-Authenticate. Vérifiez la présence de cet en-tête et l’absence de cookie wordpress_logged_in dans la réponse avant de conclure.
Faut-il renommer wp-login.php pour se protéger ?
Renommer ou déplacer la page réduit le bruit dans les journaux mais n’arrête pas un scanner qui suit le lien de connexion du site. Placez plutôt une authentification serveur ou une restriction d’adresses IP devant la page, quel que soit son nom.
Une extension de limitation de tentatives suffit-elle ?
Non contre une attaque distribuée : sur notre mois, 238 adresses sur 380 se sont arrêtées avant la troisième tentative, donc sous le seuil de blocage habituel, puis d’autres adresses ont pris le relais. L’extension reste utile pour journaliser et pour freiner les scripts les plus simples.
Commentaires (0)
Laisser un commentaire
Les commentaires sont modérés. Questions WordPress, cybersécurité ou dev web bienvenues.