Wie diese Prüfung funktioniert
Diese Prüfung läuft nur, wenn deine Seite WordPress ist, was sie am Vorkommen von wp-content oder wp-includes im HTML der Startseite erkennt. Fehlen beide, tut sie nichts. Sind sie da, testet sie drei häufige Lecks. Erstens: das Tag <meta name="generator" content="WordPress 6.x"> im HTML, das die genaue Version verrät (niedriger Schweregrad). Zweitens: die Datei /readme.html, die WordPress mit jeder Installation ausliefert und die ebenfalls die Version nennt (niedrig). Drittens: die Route /wp-json/wp/v2/users der REST-API; antwortet sie mit 200 und JSON, das die Felder slug und name enthält, gibt sie die Nutzerliste samt Login-Namen heraus (mittlerer Schweregrad).
Warum das wichtig ist
WordPress betreibt über 40 % des Webs und ist damit das Lieblingsziel automatisierter Angriffe. Diese Angriffe laufen in zwei Schritten: Version und Plugins identifizieren, um einen Exploit zu wählen, dann Passwörter gegen den Login probieren. Die exponierte Version erledigt Schritt eins. Die Nutzerliste erledigt die Hälfte von Schritt zwei: Mit dem slug jedes Nutzers (das ist der Login-Name, nicht der Anzeigename) fehlt dem Angreifer nur noch das Passwort, und das von admin, editor oder dem Namen des Inhabers wird tausendfach pro Minute probiert. Deshalb hat die Nutzerenumeration mittleren Schweregrad und die anderen beiden niedrigen.
So behebst du es
Version im Generator-Meta
In der functions.php deines Child-Themes oder in einem kleinen eigenen Plugin:
remove_action('wp_head', 'wp_generator');
Beachte, dass die Version auch in den Parametern ?ver=6.x der CSS- und JS-Dateien des Kerns steht. Sie komplett zu verbergen braucht ein Sicherheits-Plugin; was dich wirklich schützt, ist ein aktuelles WordPress, nicht die versteckte Nummer.
readme.html
Lösch sie nach jeder Installation und jedem Update (WordPress legt sie neu an) oder sperre sie am Server. In nginx: location = /readme.html { return 404; }. In Apache, in der .htaccess: <Files readme.html> Require all denied </Files>. Mach dasselbe mit license.txt.
Nutzerenumeration
Beschränke die Nutzer-Route der REST-API auf angemeldete Sitzungen. Ohne Plugin, in der functions.php:
add_filter('rest_endpoints', function ($endpoints) {
if (!is_user_logged_in()) {
unset($endpoints['/wp/v2/users']);
unset($endpoints['/wp/v2/users/(?P<id>[\d]+)']);
}
return $endpoints;
});
Die üblichen Sicherheits-Plugins (Wordfence, Solid Security, All-In-One Security) haben eine entsprechende Option. Schließ auch die alte Enumeration über ?author=1, die auf /author/name/ weiterleitet, und gib dem Login ein Versuchslimit und einen zweiten Faktor: Selbst wenn der Nutzername durchsickert, reicht das Passwort allein nicht mehr.
Prüf, ob es behoben ist
curl -s https://deinedomain.de | grep -io '<meta name="generator"[^>]*>'
curl -s -o /dev/null -w "%{http_code}\n" https://deinedomain.de/readme.html
curl -s -o /dev/null -w "%{http_code}\n" https://deinedomain.de/wp-json/wp/v2/users
Erwartet: Der erste Befehl gibt nichts zurück; der zweite 404 oder 403; der dritte 401 oder 403 (oder 404, wenn du die Route entfernt hast).
Häufige Fragen
Reicht es nicht, den Nutzer „admin" umzubenennen?
Das hilft gegen die dümmsten Angriffe, aber wenn die REST-API die Nutzer auflistet, ist der neue Name mit einer Anfrage gefunden. Benenn ihn um und schließ die Enumeration.
Mein Theme oder ein Plugin nutzt die Nutzer-REST-API im Frontend.
Selten, aber bei manchen Autorenverzeichnissen kommt das vor. Dann beschränke statt die Route zu entfernen die zurückgegebenen Felder (ohne slug) oder schränke sie nach Nutzerrechten ein. Teste es vorher in einer Staging-Umgebung.
Schaut diese Prüfung auf verwundbare Plugins?
Nein; sie schaut auf Lecks der Basisinstallation. Veraltete Plugins werden teilweise von veraltete Bibliotheken erkannt. Und wenn WP_DEBUG_LOG aktiv ist, deckt offengelegte Logs die öffentliche Datei ab, die es erzeugt.