2026年11月12日
2026年11月12日
Jak ukryć wersję WordPress: generator, ver= i readme.html
Ten artykuł jest zlokalizowaną wersją japońskiego oryginału. Przeczytaj japoński oryginał
W stanie początkowym WordPress zapisuje swój numer wersji w HTML stron i w kanałach. Atakujący mogą na jego podstawie sprawdzać, czy dana wersja ma znane luki. W tym artykule pokazuję, gdzie wersja jest widoczna i jak ją ukryć. Treść odpowiada stanowi na październik 2026.
Na początku warto wiedzieć jedno: ukrywanie wersji to tylko środek pomocniczy. Wersję można też zgadnąć choćby z zawartości plików CSS i JavaScript, więc ukrycie nie zawsze uniemożliwia jej ustalenie. Najlepiej działa utrzymywanie rdzenia WordPress, wtyczek i motywów w najnowszych wersjach.
Gdzie wyświetla się wersja
| Miejsce | Co jest wyświetlane | Rozwiązanie |
|---|---|---|
<head> w HTML |
Tag w rodzaju <meta name="generator" content="WordPress 6.9.4"> |
Filtr the_generator |
| Kanały RSS i Atom | Wiersz w rodzaju <generator>https://wordpress.org/?v=6.9.4</generator> |
Również filtr the_generator |
| Adresy URL CSS i JavaScript | ?ver= w rodzaju style.min.css?ver=6.9.4 |
Filtry style_loader_src i script_loader_src |
| Nagłówki HTTP | X-Powered-By: PHP/8.3.x (to wersja PHP, nie WordPress) |
expose_php w php.ini |
readme.html |
Informacja, że używasz WordPress (obecny readme.html nie zawiera numeru wersji) | Zablokuj dostęp |
Informacje o witrynie zwracane przez /wp-json/ w REST API (nazwa, opis, URL, strefa czasowa, przestrzenie nazw itp.) nie zawierają wersji WordPress. Aby ukryć wersję, nie trzeba przycinać danych wyjściowych REST API.
Krok 1: sprawdź, co jest teraz wyświetlane
Zamień adres na adres własnej witryny i wykonaj polecenia na swoim komputerze lub serwerze. Jeśli korzystasz z wtyczek cache lub CDN, po zmianie wyczyść cache, a dopiero potem sprawdzaj.
# Tag generator w HTML
curl -s https://example.com/ | grep -i 'name="generator"'
# Generator w kanale
curl -s https://example.com/feed/ | grep -i '<generator>'
# Lista wartości ver= dopisanych do CSS i JS
curl -s https://example.com/ | grep -oE 'ver=[0-9][0-9.]*' | sort | uniq -c
# Nagłówek HTTP X-Powered-By
curl -sI https://example.com/ | grep -i 'x-powered-by'
# Czy readme.html da się otworzyć (200 oznacza, że tak)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html
Jeśli na liście ver= jest wartość taka sama jak wersja WordPress wyświetlana w panelu w „Kokpit" → „Aktualizacje" (Dashboard → Updates), to z tych plików CSS lub JS można poznać wersję WordPress. Gdy rdzeń WordPress lub motyw ładuje CSS i JS bez podania wersji, do ver= trafia wersja WordPress.
Krok 2: wybierz, gdzie umieścić kod
Kod z tego artykułu umieść w jednym z dwóch miejsc.
- mu-plugin (zalecane): jeśli umieścisz plik PHP w katalogu
wp-content/mu-plugins/(utwórz go, jeśli nie istnieje), zostanie wczytany bez włączania. Efekt zostaje po zmianie motywu - functions.php motywu potomnego: jeśli wpiszesz to w functions.php motywu nadrzędnego, zniknie przy aktualizacji motywu
Jeśli wybierasz mu-plugin, zapisz kod z następnego kroku w jednym pliku o nazwie w rodzaju wp-content/mu-plugins/hide-wp-version.php.
Krok 3: ukryj wersję w tagu generator i w ver=
<?php
/**
* Plugin Name: Hide WordPress Version
* Description: Ukrywa wersję WordPress widoczną w tagu generator i w ver= w CSS i JS.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Opróżnia <meta name="generator"> w HTML i <generator> w kanale.
add_filter( 'the_generator', '__return_empty_string' );
/**
* Tylko gdy ver= w CSS i JS jest taki sam jak wersja WordPress, zastępuje go inną wartością.
* Nie usuwa ver=, tylko go zastępuje, więc cache przeglądarki odświeża się po aktualizacji WordPress.
*/
function wpdr_replace_wp_version_query( $src ) {
if ( ! is_string( $src ) || '' === $src ) {
return $src;
}
$query = wp_parse_url( $src, PHP_URL_QUERY );
if ( empty( $query ) ) {
return $src;
}
parse_str( $query, $args );
$wp_version = get_bloginfo( 'version' );
if ( isset( $args['ver'] ) && $args['ver'] === $wp_version ) {
$src = add_query_arg( 'ver', substr( wp_hash( $wp_version ), 0, 10 ), $src );
}
return $src;
}
add_filter( 'style_loader_src', 'wpdr_replace_wp_version_query', 20 );
add_filter( 'script_loader_src', 'wpdr_replace_wp_version_query', 20 );
Najważniejsze punkty:
- Filtr
the_generatordziała zarówno na tag generator w HTML, jak i na generator w kanale.remove_action( 'wp_head', 'wp_generator' );usuwa tylko tag w HTML, więc nie działa na kanał - Jeśli usuniesz wszystkie
?ver=, po aktualizacji wtyczek lub motywów przeglądarka może dalej używać starych CSS i JS. Powyższy kod zastępuje wartość innym ciągiem utworzonym z wersji tylko wtedy, gdy jest równa wersji WordPress. Po aktualizacji WordPress wartość też się zmienia, więc cache się odświeża - Wartości
ver=z własnymi numerami wersji nadawanymi przez wtyczki lub motywy nie są zmieniane
Po zapisaniu sprawdź poleceniami z kroku 1, że generator nie jest wyświetlany i że na liście ver= nie została wersja WordPress. Jeśli używasz wtyczek cache, wyczyść cache, zanim sprawdzisz.
Krok 4: wyłącz nagłówek X-Powered-By
X-Powered-By to nagłówek dodawany nie przez WordPress, lecz przez PHP i ujawnia wersję PHP. Aby go wyłączyć, ustaw expose_php na Off w pliku konfiguracyjnym PHP (php.ini). To ustawienie można zmienić tylko w php.ini.
expose_php = Off
To przykład dla Ubuntu na VPS z PHP-FPM (8.3 dopasuj do używanej wersji PHP).
# Sprawdź obecne ustawienie
grep -n '^expose_php' /etc/php/8.3/fpm/php.ini
# Po zmianie uruchom ponownie PHP-FPM
sudo systemctl restart php8.3-fpm
W pakietowym php.ini w Ubuntu domyślnie jest expose_php = Off. Jeśli nagłówek mimo to się pojawia, sprawdź, czy nie jest używany inny php.ini. Na hostingach ustawienie to można czasem zmienić w ustawieniach PHP w panelu, a czasem nie.
Jeśli nie możesz zmienić php.ini, nagłówek da się usunąć też kodem WordPress. Hak send_headers jest jednak uruchamiany przez WordPress przy wyświetlaniu stron frontendu, więc nie działa w panelu administracyjnym ani na ekranie logowania.
add_action( 'send_headers', function () {
header_remove( 'X-Powered-By' );
} );
Krok 5: zablokuj dostęp do readme.html i license.txt
readme.html i license.txt to pliki rdzenia WordPress. Obecny readme.html nie zawiera numeru wersji, ale ujawnia, że używasz WordPress.
Nawet jeśli je usuniesz, wrócą po aktualizacji rdzenia WordPress. Mniej pracy niż usuwanie wymaga zablokowanie dostępu na serwerze WWW.
Apache (.htaccess)
Dopisz do pliku .htaccess w katalogu WordPress. Fragment między # BEGIN WordPress a # END WordPress jest przepisywany przez WordPress, więc wpisz to poza nim. To składnia Apache 2.4 (Order i Deny from all to stara składnia Apache 2.2).
<FilesMatch "^(readme\.html|license\.txt)$">
Require all denied
</FilesMatch>
Nginx
Dopisz do bloku server witryny, sprawdź konfigurację i przeładuj.
location ~* ^/(readme\.html|license\.txt)$ {
deny all;
}
sudo nginx -t && sudo systemctl reload nginx
Po dopisaniu uruchom curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html i sprawdź, czy wraca 403.
Czego ukrycie nie zabezpiecza
- Zawartość plików CSS i JS WordPress różni się nieznacznie między wersjami, więc po pobraniu plików i porównaniu da się odgadnąć wersję
- Z
readme.txtlubver=wtyczek i motywów można czasem poznać wersje wtyczek. Atakowane są częściej luki we wtyczkach niż w rdzeniu - Osoby, które mogą zalogować się do panelu, nadal widzą wersję jak dotąd
Dlatego razem z ukrywaniem wersji aktualizuj rdzeń, wtyczki i motywy, usuwaj nieużywane wtyczki i wyłącz edycję plików w panelu administracyjnym.
Podsumowanie
- Wersja pojawia się głównie w generatorze w HTML i w kanałach oraz w
?ver=w CSS i JS./wp-json/w REST API nie zawiera wersji WordPress - Przez
add_filter( 'the_generator', '__return_empty_string' );usuniesz generator zarówno z HTML, jak i z kanału - Nie usuwaj
?ver=, tylko zastępuj wyłącznie wartość równą wersji WordPress — wtedy odświeżanie cache nie zostanie zatrzymane X-Powered-Bywyłączysz przezexpose_php = Offw php.inireadme.htmlpo usunięciu wraca przy aktualizacji, więc zablokuj do niego dostęp na serwerze WWW- Ukrywanie to środek pomocniczy; najważniejsze jest ciągłe aktualizowanie
Powiązane artykuły:
- Jak skonfigurować nagłówki bezpieczeństwa w WordPress | osobno .htaccess, Nginx i functions.php
- Jak ograniczyć dostęp do REST API w WordPress
- Wyłączanie edytora plików motywów i wtyczek w WordPress | DISALLOW_FILE_EDIT
Pytania o WordPress? Wydawca tej witryny ma siedzibę w Japonii i odpowiada po japońsku. Kontakt (po japońsku)