WordPress User Enumeration: REST API und Autoren-URLs
WordPress User Enumeration: Prüfen Sie, welche Login-Namen REST API, Autoren-URLs, Sitemap und Login-Fehler verraten, und schließen Sie die Lücken gezielt.
Auch auf: English Français Español Italiano Polski Português Türkçe
Bei einer WordPress-Standardinstallation findet in der Regel jeder Ihre Login-Namen in weniger als einer Minute. WordPress User Enumeration nutzt dafür fünf bis sechs eingebaute Kanäle: die REST API, Weiterleitungen von ?author=1, Autorenarchiv-URLs, die Benutzer-Sitemap, Fehlermeldungen beim Login und teilweise auch Feeds und oEmbed-Daten. Dieser Artikel zeigt, wie Sie jeden dieser Kanäle auf Ihrer eigenen Website prüfen und mit einer gezielten Maßnahme schließen, ohne dass der Block-Editor dabei kaputtgeht.
Was WordPress User Enumeration ist und wie viel sie ausmacht
User Enumeration bedeutet, gültige Kontonamen einer Website zu sammeln. Wer weiß, dass es mkeller gibt, muss nicht mehr admin, info und test raten. Jeder Passwortversuch und jedes Passwort aus fremden Datenlecks landet dann bei einem Konto, das tatsächlich existiert.
Machen Sie sich klar, was das Verstecken der Namen bringt: Es ist ein Bremsklotz, kein Schutz. Eine Kontoübernahme verhindern Zwei-Faktor-Authentifizierung und eine Drosselung der Login-Versuche. Richten Sie diese zuerst ein (Zwei-Faktor-Authentifizierung für WordPress, Schutz vor Brute-Force-Angriffen). Danach schließen Sie die unten beschriebenen Lecks, und zwar in dieser Reihenfolge: testen, beheben, erneut testen.
Testen Sie Ihre eigene Website: sechs Stellen, an denen Benutzernamen durchsickern
Führen Sie diese Tests nur gegen Websites aus, die Ihnen gehören oder die Sie betreuen. Testen Sie abgemeldet, also im Terminal oder in einem privaten Browserfenster, denn angemeldete Sitzungen sehen mehr. Ersetzen Sie example.com durch Ihre Domain.
- REST API. WordPress listet hier Benutzer auf, die Inhalte veröffentlicht haben. Achten Sie auf das Feld
slug: Das ist der Autoren-Slug, und er stimmt meist mit dem Login-Namen überein.
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":"[^"]*"'
- Weiterleitungen per Autor-ID. WordPress leitet
?author=Nauf die sprechende Autoren-URL weiter. Probieren Sie 1, 2, 3 und so weiter.
curl -sI "https://example.com/?author=1" | grep -i '^location'
- HTML des Themes. Autorenlinks unter Beiträgen und CSS-Klassen wie
comment-author-<slug>bei Kommentaren registrierter Benutzer.
curl -s https://example.com/a-post/ | grep -oE '/author/[^/"]+/|comment-author-[a-z0-9-]+' | sort -u
- Benutzer-Sitemap. Öffnen Sie
https://example.com/wp-sitemap-users-1.xmlim Browser.
- Login-Fehlermeldungen. Geben Sie auf
wp-login.phperst einen erfundenen Benutzernamen ein, dann einen echten mit falschem Passwort. Unterscheiden sich die Meldungen, bestätigt das Formular gültige Konten. Das Formular „Passwort vergessen“ verhält sich genauso. Bleiben Sie bei zwei oder drei Versuchen, damit Ihre eigene Drosselung Sie nicht aussperrt.
- Feeds und oEmbed. Der Feed zeigt Anzeigenamen in
dc:creator. Der oEmbed-Endpunkt liefertauthor_nameundauthor_url, und diese URL enthält den Autoren-Slug.
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/"
| Kanal | Test | Verrät |
|---|---|---|
| REST-Benutzer | /wp-json/wp/v2/users | Slug, Name, ID |
| Autor-Weiterleitung | /?author=1 | Slug im Location-Header |
| Theme-HTML | Markup von Beiträgen und Kommentaren | Slug |
| Benutzer-Sitemap | /wp-sitemap-users-1.xml | Autoren-URLs mit Slug |
| Login-Fehler | Unbekannter Name vs. falsches Passwort | Gültige Logins |
| Feed / oEmbed | dc:creator, author_url | Anzeigename, Slug |
Wer ein strukturiertes Vorgehen sucht: Der OWASP Web Security Testing Guide behandelt Tests auf Account Enumeration ausführlicher.
REST-Endpunkt für Benutzer nur für anonyme Besucher sperren
Greifen Sie nur in die Benutzer-Route ein, und nur bei Anfragen ohne angemeldeten Benutzer. Der Block-Editor nutzt /wp/v2/users für die Autorenauswahl, und mobile Apps sowie viele Plugins rufen den Endpunkt authentifiziert auf. Entfernen Sie die Route für alle, funktioniert all das nicht mehr.
Legen Sie die Datei wp-content/mu-plugins/user-enumeration.php an. Must-Use-Plugins werden automatisch geladen und lassen sich im Dashboard nicht deaktivieren. Mit dem Filter rest_endpoints entfernen Sie Routen, bevor sie ausgeliefert werden:
<?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;
} );
Führen Sie den curl-Test erneut aus. Sie sollten jetzt einen Fehler rest_no_route mit Status 404 erhalten. Melden Sie sich anschließend an, öffnen Sie einen Beitrag im Editor und prüfen Sie, ob das Autorenfeld weiterhin Benutzer anzeigt.
Betreiben Sie ein Headless-Frontend oder eine App, die Autorendaten ohne Anmeldung liest, macht dieses Snippet sie kaputt. Stellen Sie in diesem Fall nur die benötigten Felder über einen eigenen Endpunkt bereit. Welche Daten der Endpunkt liefert, steht in der Referenz zum REST-API-Endpunkt Users.
Autor-ID-Weiterleitungen stoppen und klären, ob Sie Autorenarchive brauchen
Ruft jemand /?author=2 auf, ermittelt WordPress den Benutzer, und die kanonische Weiterleitung schickt den Besucher nach /author/<slug>/. Der Location-Header verrät den Slug, und ein Skript arbeitet sich in Sekunden durch die IDs 1 bis 50.
Ergänzen Sie dasselbe Must-Use-Plugin unterhalb des ersten Snippets um den folgenden Code. Er läuft vor der kanonischen Weiterleitung und beantwortet anonyme Anfragen mit author-Parameter mit einem schlichten 404, sodass kein Location-Header den Slug preisgibt:
add_action( 'template_redirect', function () {
if ( is_user_logged_in() ) {
return;
}
if ( isset( $_GET['author'] ) ) {
wp_die( 'Not found.', '', array( 'response' => 404 ) );
}
}, 1 );
Testen Sie erneut mit curl -sI "https://example.com/?author=1". Jetzt sollten Sie einen 404 ohne Location-Header erhalten.
Auf einem Firmenblog mit nur einem Autor oder einer Website ohne öffentliche Autorenseiten gehen Sie einen Schritt weiter und schalten die Autorenarchive ganz ab. Die meisten SEO-Plugins haben dafür eine Einstellung, manche Themes ebenfalls. Die Grenze dieser Maßnahme sollten Sie kennen: Gibt Ihr Theme unter jedem Beitrag einen Link „von <Autor>“ aus, steht der Slug weiterhin im HTML. Darum geht es in den nächsten beiden Abschnitten.
Benutzer-Sitemap entfernen, wo sie niemand braucht
Die mit WordPress 5.5 eingeführten Core-Sitemaps enthalten einen Benutzer-Provider, der jedes Autorenarchiv auflistet. Die wenigsten Unternehmenswebsites haben davon einen Nutzen. Der Filter wp_sitemaps_add_provider entfernt ihn:
add_filter( 'wp_sitemaps_add_provider', function ( $provider, $name ) {
if ( 'users' === $name ) {
return false;
}
return $provider;
}, 10, 2 );
Rufen Sie /wp-sitemap-users-1.xml erneut auf; die Seite sollte jetzt einen 404 liefern. Ersetzt ein SEO-Plugin die Core-Sitemaps, wirkt dieser Filter nicht auf dessen Ausgabe. Suchen Sie dann in den Sitemap-Einstellungen des Plugins nach einer Autoren-Sitemap und schalten Sie sie dort ab.
Anzeigenamen und Autoren-Slugs von Login-Namen trennen
Tragen Sie unter Benutzer > Profil einen Spitznamen ein und wählen Sie ihn unter Name öffentlich anzeigen als aus. Damit sind Feeds, author_name in oEmbed und die „von“-Zeilen abgedeckt.
Jetzt kommt die Falle. Der Autoren-Slug (user_nicename) wird beim Anlegen des Kontos aus dem Login-Namen erzeugt und ändert sich nicht, wenn Sie den Anzeigenamen ändern. Ihre Beiträge zeigen dann vielleicht „Redaktion“, während die URL weiterhin /author/mkeller/ lautet. Beheben Sie das mit 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
Verwenden Sie Kleinbuchstaben, Ziffern und Bindestriche, und jeder Slug muss eindeutig sein. Die bisherigen Autoren-URLs ändern sich. Rechnen Sie also mit einigen 404-Fehlern oder richten Sie eine Weiterleitung ein, falls diese Seiten Besucher hatten.
Vermeiden Sie bei neuen Konten admin, den Firmennamen und den Domainnamen als Login. Sind alte oder gemeinsam genutzte Konten Teil des Problems, räumen Sie diese zuerst auf: Sicherheit von WordPress-Benutzerrollen.
Einheitliche Login-Fehlermeldungen
Der Filter login_errors ersetzt die Meldungen auf der Login-Seite durch einen einzigen neutralen Text:
add_filter( 'login_errors', function () {
return '<strong>Error:</strong> The login details are incorrect.';
} );
Damit verschwinden auch hilfreiche Hinweise, etwa der auf ein leeres Feld, und Ihre Benutzer bekommen weniger Orientierung. Undurchsichtig wird die Website dadurch trotzdem nicht. Das Formular „Passwort vergessen“ verhält sich bei gültigen Konten weiterhin anders, denn ein echtes Konto führt zur Aufforderung, das E-Mail-Postfach zu prüfen. Manche Plugins bringen eigene Login-Formulare mit, und die Seite „Mein Konto“ von WooCommerce hat eigene Meldungen. Sehen Sie diese Maßnahme als Frage der Einheitlichkeit, nicht als starke Schutzmaßnahme.
Was das Verstecken von Benutzernamen nicht verhindert
Angreifer probieren gängige Namen und E-Mail-Adressen durch, ob Ihre Website sie verrät oder nicht, und WordPress akzeptiert die E-Mail-Adresse als Login. Credential Stuffing, also das Durchprobieren von Benutzername-Passwort-Paaren aus anderen Datenlecks, kommt ganz ohne Enumeration aus. Gegen ein wiederverwendetes Passwort hilft auch die perfekt versteckte Benutzerliste nichts.
Für die Website eines kleinen Unternehmens gilt daher diese Reihenfolge:
- Zwei-Faktor-Authentifizierung für alle Administratoren und Redakteure (Anleitung).
- Drosselung der Login-Versuche und eine Entscheidung zu XML-RPC (Schutz vor Brute-Force-Angriffen).
- Die oben beschriebenen Maßnahmen gegen Enumeration, geprüft mit den curl-Befehlen.
- Das Ergebnis in Ihre regelmäßige Überprüfung aufnehmen (WordPress-Sicherheitscheckliste).
Das Plugin Security Audit & Compliance von secaudit.eu enthält eine Login-Drosselung und ein Rate Limiting für anonyme REST-Anfragen. Sein Hardening-Scan meldet Konfigurationsbefunde, sodass Sie sehen, was noch offen ist → secaudit.eu
Ihr nächster Schritt: Führen Sie die sechs Tests aus diesem Artikel noch heute gegen Ihre Website aus, dokumentieren Sie die Ergebnisse und schließen Sie die Kanäle, die einen echten Login-Namen zeigen.
FAQ
Legt das Sperren von /wp/v2/users den Block-Editor lahm?
Nicht, wenn Sie die Sperre wie im Snippet oben auf anonyme Anfragen beschränken. Der Editor sendet authentifizierte Anfragen, die Autorenauswahl funktioniert also weiter. Würden Sie die Route auch für angemeldete Benutzer entfernen, wäre sie kaputt.
Ist „admin“ mit 2FA noch ein Risiko?
Ein deutlich kleineres. Mit 2FA reicht ein erratenes Passwort allein nicht für den Zugang. admin zieht aber ständige Rateversuche an, die die Logs füllen und Sperren auslösen können. Es lohnt sich also trotzdem, das Konto zu ersetzen.
Sollte ich den Login-Namen selbst ändern, und wie?
WordPress bietet keine Schaltfläche, um einen Login-Namen zu ändern. Legen Sie einen neuen Administrator mit neutralem Login und 2FA an, melden Sie sich damit an und löschen Sie dann das alte Konto. Wenn WordPress nachfragt, weisen Sie dessen Inhalte dem neuen Konto zu. Achten Sie darauf, dass jederzeit ein funktionierender Administrator vorhanden ist. Die Einzelheiten finden Sie unter Sicherheit von WordPress-Benutzerrollen.
Prüfen Sie Ihre eigene Website
Security Audit & Compliance ist das WordPress-Plugin von secaudit.eu: Es sucht nach Malware, verstecktem Spam, veränderten Kerndateien und unsicherem Code und ordnet seine Befunde DSGVO Art. 32, NIS2 Art. 21 und den OWASP Top 10 zu.
Sehen, was das Plugin prüft