Jak działa ta kontrola
Ta kontrola działa tylko wtedy, gdy Twoja strona to WordPress, co wykrywa po obecności wp-content lub wp-includes w HTML-u strony głównej. Jeśli ich nie ma, nic nie robi. Jeśli są, testuje trzy typowe wycieki. Pierwszy: znacznik <meta name="generator" content="WordPress 6.x"> w HTML-u, który ujawnia dokładną wersję (niska waga). Drugi: plik /readme.html, który WordPress dołącza do każdej instalacji i który też podaje wersję (niska). Trzeci: ścieżka /wp-json/wp/v2/users REST API; jeśli odpowiada 200 z JSON-em zawierającym pola slug i name, wydaje listę użytkowników z ich nazwami logowania (średnia waga).
Dlaczego to ważne
WordPress napędza ponad 40 % sieci, więc jest ulubionym celem zautomatyzowanych ataków. Te ataki działają w dwóch krokach: zidentyfikować wersję i wtyczki, żeby wybrać exploit, a potem próbować haseł na logowaniu. Wystawiona wersja załatwia krok pierwszy. Lista użytkowników załatwia połowę drugiego: mając slug każdego użytkownika (czyli nazwę logowania, nie nazwę wyświetlaną), atakującemu brakuje tylko hasła, a hasło do admin, editor albo nazwy właściciela jest sprawdzane tysiące razy na minutę. Dlatego enumeracja użytkowników ma średnią wagę, a pozostałe dwa niską.
Jak to naprawić
Wersja w meta generator
W functions.php motywu potomnego albo we własnej małej wtyczce:
remove_action('wp_head', 'wp_generator');
Pamiętaj, że wersja jest też widoczna w parametrach ?ver=6.x plików CSS i JS rdzenia. Ukrycie jej całkowicie wymaga wtyczki bezpieczeństwa; ale naprawdę chroni Cię aktualny WordPress, a nie ukryty numer.
readme.html
Usuń go po każdej instalacji i aktualizacji (WordPress tworzy go ponownie) albo zablokuj na serwerze. W nginx: location = /readme.html { return 404; }. W Apache, w .htaccess: <Files readme.html> Require all denied </Files>. To samo zrób z license.txt.
Enumeracja użytkowników
Ogranicz ścieżkę użytkowników REST API do zalogowanych sesji. Bez wtyczki, w 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;
});
Popularne wtyczki bezpieczeństwa (Wordfence, Solid Security, All-In-One Security) mają równoważną opcję. Zamknij też starą enumerację przez ?author=1, która przekierowuje na /author/nazwa/, i dodaj limit prób oraz drugi składnik do logowania: nawet jeśli nazwa użytkownika wycieknie, samo hasło przestaje wystarczać.
Sprawdź, czy naprawione
curl -s https://twojadomena.pl | grep -io '<meta name="generator"[^>]*>'
curl -s -o /dev/null -w "%{http_code}\n" https://twojadomena.pl/readme.html
curl -s -o /dev/null -w "%{http_code}\n" https://twojadomena.pl/wp-json/wp/v2/users
Oczekiwane: pierwsze nie zwraca nic; drugie 404 lub 403; trzecie 401 lub 403 (albo 404, jeśli usunąłeś ścieżkę).
Często zadawane pytania
Czy nie wystarczy zmienić nazwę użytkownika „admin"?
Pomaga przeciwko najgłupszym atakom, ale jeśli REST API listuje użytkowników, nową nazwę odkrywa się jednym żądaniem. Zmień nazwę i zamknij enumerację.
Mój motyw lub wtyczka używa REST API użytkowników na froncie.
Rzadkie, ale zdarza się przy niektórych katalogach autorów. Wtedy zamiast usuwać ścieżkę, ogranicz zwracane pola (bez slug) albo ogranicz ją według uprawnień użytkownika. Przetestuj najpierw w środowisku testowym.
Czy ta kontrola sprawdza podatne wtyczki?
Nie; sprawdza wycieki z instalacji bazowej. Nieaktualne wtyczki są częściowo wykrywane w przestarzałe biblioteki. A jeśli masz włączone WP_DEBUG_LOG, publiczny plik, który tworzy, obejmuje wystawione logi.