Énumération des utilisateurs WordPress : API REST et auteurs
Énumération des utilisateurs WordPress : testez quels identifiants votre site révèle (API REST, URL d'auteur, sitemap, erreurs de connexion), puis corrigez-les.
Aussi en : English Deutsch Español Italiano Polski Português Türkçe
Sur une installation WordPress par défaut, n'importe qui peut en général trouver vos identifiants de connexion en moins d'une minute. L'énumération des utilisateurs WordPress passe par cinq ou six canaux intégrés : l'API REST, les redirections ?author=1, les URL d'archives d'auteur, le sitemap des utilisateurs, les messages d'erreur de connexion et, dans certains cas, les flux et les données oEmbed. Cet article montre comment tester chaque canal sur votre propre site et le fermer avec un correctif ciblé, sans casser l'éditeur de blocs.
Qu'est-ce que l'énumération des utilisateurs, et quel enjeu ?
L'énumération des utilisateurs consiste à collecter des noms de comptes valides sur un site. Un attaquant qui sait que mkeller existe peut consacrer toutes ses tentatives de mot de passe, et tous les mots de passe issus d'autres fuites de données, à un vrai compte, plutôt que de deviner admin, info et test.
Soyons clairs sur ce que l'on obtient en masquant les noms : un ralentisseur, pas une protection. Ce qui empêche la prise de contrôle d'un compte, ce sont l'authentification à deux facteurs et la limitation des tentatives de connexion. Commencez donc par là (authentification à deux facteurs pour WordPress, protection contre la force brute). Fermez ensuite les fuites décrites ci-dessous, dans cet ordre : tester, corriger, retester.
Testez votre site : six endroits où les identifiants fuient
Ne lancez ces tests que sur des sites qui vous appartiennent ou que vous administrez. Testez en étant déconnecté, depuis un terminal ou une fenêtre de navigation privée, car une session connectée en voit davantage. Remplacez example.com par votre domaine.
- API REST. Le cœur de WordPress liste les utilisateurs qui ont publié du contenu. Regardez le champ
slug: c'est le slug d'auteur, généralement identique à l'identifiant de connexion.
curl -s https://example.com/wp-json/wp/v2/users | grep -o '"slug":"[^"]*"'
curl -s "https://example.com/?rest_route=/wp/v2/users" | grep -o '"slug":"[^"]*"'
- Redirections par ID d'auteur. WordPress redirige
?author=Nvers l'URL d'auteur lisible. Essayez 1, 2, 3, etc.
curl -sI "https://example.com/?author=1" | grep -i '^location'
- HTML du thème. Les liens d'auteur sous les articles et les classes CSS comme
comment-author-<slug>sur les commentaires d'utilisateurs inscrits.
curl -s https://example.com/a-post/ | grep -oE '/author/[^/"]+/|comment-author-[a-z0-9-]+' | sort -u
- Sitemap des utilisateurs. Ouvrez
https://example.com/wp-sitemap-users-1.xmldans le navigateur.
- Erreurs de connexion. Sur
wp-login.php, saisissez un identifiant inventé, puis un identifiant réel avec un mauvais mot de passe. Si les messages diffèrent, le formulaire confirme les comptes valides. Le formulaire de mot de passe oublié se comporte de la même façon. Limitez-vous à deux ou trois essais pour que votre propre limitation ne vous verrouille pas.
- Flux et oEmbed. Le flux affiche les noms publics dans
dc:creator. Le point d'accès oEmbed renvoieauthor_nameetauthor_url, et cette URL contient le slug d'auteur.
curl -s https://example.com/feed/ | grep -i 'dc:creator'
curl -s "https://example.com/wp-json/oembed/1.0/embed?url=https://example.com/a-post/"
| Canal | Test | Révèle |
|---|---|---|
| Utilisateurs REST | /wp-json/wp/v2/users | Slug, nom, ID |
| Redirection d'auteur | /?author=1 | Slug dans Location |
| HTML du thème | Balisage des articles et commentaires | Slug |
| Sitemap utilisateurs | /wp-sitemap-users-1.xml | URL d'auteur avec slug |
| Erreurs de connexion | Inconnu ou mauvais mot de passe | Identifiants valides |
| Flux / oEmbed | dc:creator, author_url | Nom public, slug |
Si vous voulez une méthode structurée, l'OWASP Web Security Testing Guide traite plus en profondeur du test d'énumération de comptes.
Restreindre le point d'accès REST des utilisateurs, pour les visiteurs anonymes uniquement
Ne visez que la route des utilisateurs, et uniquement pour les requêtes sans utilisateur connecté. L'éditeur de blocs utilise /wp/v2/users pour le sélecteur d'auteur, et les applications mobiles comme de nombreuses extensions l'appellent en étant authentifiées. Supprimez la route pour tout le monde et tout cela cesse de fonctionner.
Créez wp-content/mu-plugins/user-enumeration.php. Les extensions « must-use » se chargent automatiquement et ne peuvent pas être désactivées depuis le tableau de bord. Le filtre rest_endpoints permet de retirer des routes avant qu'elles ne soient servies :
<?php
/**
* Plugin Name: Limit user enumeration
*/
add_filter( 'rest_endpoints', function ( $endpoints ) {
if ( is_user_logged_in() ) {
return $endpoints;
}
unset( $endpoints['/wp/v2/users'] );
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
return $endpoints;
} );
Relancez le test curl. Vous devriez maintenant obtenir une erreur rest_no_route avec le statut 404. Connectez-vous ensuite, ouvrez un article dans l'éditeur et vérifiez que le panneau d'auteur liste toujours les utilisateurs.
Si vous exploitez un front-end headless ou une application qui lit anonymement les données d'auteur, cet extrait la cassera. Dans ce cas, n'exposez que les champs nécessaires via un point d'accès personnalisé. La référence de l'API REST pour les utilisateurs liste ce que renvoie ce point d'accès.
Bloquer les redirections par ID d'auteur et décider si vous avez besoin des archives d'auteur
Quand quelqu'un demande /?author=2, WordPress identifie l'utilisateur et sa redirection canonique envoie le visiteur vers /author/<slug>/. L'en-tête Location trahit le slug, et un script peut parcourir les ID de 1 à 50 en quelques secondes.
Ajoutez ceci sous le premier extrait, dans le même mu-plugin. Il s'exécute avant la redirection canonique et répond par un simple 404 aux requêtes anonymes comportant un paramètre author, si bien qu'aucun en-tête Location ne livre le slug :
add_action( 'template_redirect', function () {
if ( is_user_logged_in() ) {
return;
}
if ( isset( $_GET['author'] ) ) {
wp_die( 'Not found.', '', array( 'response' => 404 ) );
}
}, 1 );
Retestez avec curl -sI "https://example.com/?author=1". Vous devriez obtenir un 404 et aucun en-tête Location.
Sur le blog d'une entreprise avec un seul auteur, ou sur un site sans pages d'auteur publiques, allez plus loin et désactivez les archives d'auteur. La plupart des extensions SEO proposent un réglage pour cela, et certains thèmes aussi. Gardez en tête la limite : si votre thème affiche des liens « par <auteur> » sous chaque article, le slug reste présent dans le HTML. C'est l'objet des deux sections suivantes.
Supprimer le sitemap des utilisateurs là où il ne sert à personne
Les sitemaps natifs, apparus avec WordPress 5.5, comprennent un fournisseur « users » qui liste toutes les archives d'auteur. Peu de sites d'entreprise y gagnent quoi que ce soit. Le filtre wp_sitemaps_add_provider le retire :
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
if ( 'users' === $name ) {
return false;
}
return $provider;
}, 10, 2 );
Ouvrez à nouveau /wp-sitemap-users-1.xml : il doit maintenant renvoyer un 404. Si une extension SEO remplace les sitemaps natifs, ce filtre n'a aucun effet sur sa sortie. Cherchez dans les réglages de sitemap de l'extension un sitemap des auteurs et désactivez-le à cet endroit.
Différencier noms publics et slugs d'auteur des identifiants de connexion
Dans Utilisateurs > Profil, définissez un Pseudonyme et sélectionnez-le sous Afficher publiquement le nom en tant que. Cela couvre les flux, le champ oEmbed author_name et les mentions « par ».
Voici le piège. Le slug d'auteur (user_nicename) est généré à partir de l'identifiant à la création du compte et ne change pas quand vous modifiez le nom public. Vos articles peuvent afficher « Équipe éditoriale » alors que l'URL indique toujours /author/mkeller/. Corrigez cela avec WP-CLI :
wp db export before-nicename.sql
wp user list --fields=ID,user_login,user_nicename,display_name
wp user update 2 --user_nicename=editorial-team
Utilisez des minuscules, des chiffres et des tirets, et gardez chaque slug unique. Les anciennes URL d'auteur changent : attendez-vous à quelques 404, ou ajoutez une redirection si ces pages recevaient du trafic.
Pour les nouveaux comptes, évitez admin, le nom de l'entreprise et le nom de domaine comme identifiants. Si d'anciens comptes ou des comptes partagés font partie du problème, nettoyez-les d'abord : sécurité des rôles utilisateur WordPress.
Des messages d'erreur de connexion génériques
Le filtre login_errors remplace les messages affichés sur l'écran de connexion par un texte neutre unique :
add_filter( 'login_errors', function () {
return '<strong>Error:</strong> The login details are incorrect.';
} );
Il remplace aussi les messages utiles, comme l'indication de champ vide : vos utilisateurs sont donc moins guidés. Il ne rend pas pour autant le site opaque. Le formulaire de mot de passe oublié se comporte toujours différemment pour un compte valide, puisqu'un vrai compte mène à l'écran « vérifiez votre e-mail ». Certaines extensions ajoutent leurs propres formulaires de connexion, et la page Mon compte de WooCommerce a ses propres messages. Voyez-y un gain de cohérence, pas un contrôle fort.
Ce que le masquage des identifiants n'empêche pas
Les attaquants essaient les noms courants et les adresses e-mail, que votre site fuite ou non, et WordPress accepte l'adresse e-mail comme identifiant. Le credential stuffing, qui rejoue des couples identifiant/mot de passe issus d'autres fuites, n'a besoin d'aucune énumération. Une liste d'utilisateurs parfaitement masquée ne sert à rien face à un mot de passe réutilisé.
Voici donc l'ordre à suivre pour le site d'une petite entreprise :
- Authentification à deux facteurs pour chaque administrateur et éditeur (guide de mise en place).
- Limitation des tentatives de connexion et décision sur XML-RPC (protection contre la force brute).
- Les correctifs d'énumération ci-dessus, testés avec les commandes curl.
- Intégrer le résultat à votre revue régulière (checklist de sécurité WordPress).
L'extension Security Audit & Compliance de secaudit.eu inclut la limitation des tentatives de connexion et une limitation de débit pour l'API REST anonyme ; son analyse de durcissement signale les constats de configuration, pour que vous voyiez ce qui reste ouvert → secaudit.eu
Prochaine étape : lancez dès aujourd'hui les six tests de cet article sur votre site, consignez les résultats et corrigez les canaux qui montrent un vrai identifiant de connexion.
FAQ
Bloquer /wp/v2/users casse-t-il l'éditeur de blocs ?
Non, à condition de le restreindre aux requêtes anonymes, comme dans l'extrait ci-dessus. L'éditeur envoie des requêtes authentifiées, donc le sélecteur d'auteur continue de fonctionner. Supprimer la route pour les utilisateurs connectés le casserait.
« admin » reste-t-il un risque si j'ai la 2FA ?
Beaucoup moins. Avec la 2FA, un mot de passe deviné ne suffit plus à entrer. Mais admin attire des tentatives incessantes, qui remplissent les journaux et peuvent déclencher des verrouillages ; il vaut donc toujours la peine de le remplacer.
Dois-je renommer l'identifiant lui-même, et comment ?
WordPress n'a pas de bouton pour changer un identifiant. Créez un nouvel administrateur avec un identifiant neutre et la 2FA, connectez-vous avec lui, puis supprimez l'ancien compte et attribuez son contenu au nouveau lorsque WordPress vous le demande. Gardez à tout moment un administrateur fonctionnel. Les détails sont dans sécurité des rôles utilisateur WordPress.
Vérifiez votre propre site
Security Audit & Compliance est l’extension WordPress de secaudit.eu : elle recherche les logiciels malveillants, le spam caché, les fichiers du cœur modifiés et le code vulnérable, et rattache ses constats à l’article 32 du RGPD, à l’article 21 de NIS2 et à l’OWASP Top 10.
Voir ce que vérifie l’extension