2026年11月12日
2026年11月12日
隱藏 WordPress 版本資訊的方法|generator 標籤、ver=、readme.html
本文是日文原文的在地化版本。 閱讀日文原文
WordPress 在初始狀態下,會把自己的版本號碼寫進頁面的 HTML 與 feed 中。攻擊者可能會看這個資訊,作為判斷是否為有已知漏洞版本的線索。本文會確認版本顯示在哪些地方,並說明隱藏的步驟。內容為 2026 年 10 月時的資訊。
首先希望你知道的是,隱藏版本只是輔助性的對策。因為也有從 CSS 或 JavaScript 檔案的內容等推測版本的方法,所以即使隱藏,也不一定能防止被辨識出來。最有效的是讓 WordPress 核心、外掛、佈景主題保持在最新版本。
版本會顯示的地方
| 位置 | 顯示的內容 | 對策 |
|---|---|---|
HTML 的 <head> |
像 <meta name="generator" content="WordPress 6.9.4"> 這樣的標籤 |
the_generator 篩選器 |
| RSS、Atom feed | 像 <generator>https://wordpress.org/?v=6.9.4</generator> 這樣的行 |
同樣使用 the_generator 篩選器 |
| CSS、JavaScript 的 URL | 像 style.min.css?ver=6.9.4 這樣的 ?ver= |
style_loader_src、script_loader_src 篩選器 |
| HTTP 標頭 | X-Powered-By: PHP/8.3.x(不是 WordPress 而是 PHP 的版本) |
php.ini 的 expose_php |
readme.html |
會顯示出使用 WordPress(目前的 readme.html 裡沒有寫版本號碼) | 拒絕存取 |
REST API 的 /wp-json/ 回傳的網站資訊(名稱、說明、URL、時區、命名空間等)中,不包含 WordPress 的版本。不需要為了隱藏版本而刪減 REST API 的輸出。
步驟 1:確認目前的顯示狀態
請換成自己網站的 URL,在自己的電腦或伺服器上執行。如果使用快取類外掛或 CDN,變更後請先清除快取再確認。
# HTML 的 generator 標籤
curl -s https://example.com/ | grep -i 'name="generator"'
# feed 的 generator
curl -s https://example.com/feed/ | grep -i '<generator>'
# 列出 CSS、JS 上附帶的 ver= 的值
curl -s https://example.com/ | grep -oE 'ver=[0-9][0-9.]*' | sort | uniq -c
# HTTP 標頭的 X-Powered-By
curl -sI https://example.com/ | grep -i 'x-powered-by'
# readme.html 是否可以讀取(200 代表可以讀取)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html
如果 ver= 的清單中,有和後台「儀表板」(Dashboard)→「更新」(Updates)所顯示的 WordPress 版本相同的值,就表示可以從那些 CSS 或 JS 得知 WordPress 的版本。WordPress 核心或佈景主題載入 CSS、JS 時如果沒有指定版本,WordPress 的版本就會被放進 ver=。
步驟 2:決定程式碼要放的位置
本文的程式碼,請放在下列任一處。
- mu-plugin(建議):在
wp-content/mu-plugins/資料夾(沒有的話就建立)中放入 PHP 檔案,不需要啟用操作就會被載入。更換佈景主題後效果仍然持續 - 子佈景主題的 functions.php:如果寫在父佈景主題的 functions.php,會在佈景主題更新時消失
如果採用 mu-plugin,請用像 wp-content/mu-plugins/hide-wp-version.php 這樣的名稱,把下一個步驟的程式碼整合成一個檔案儲存。
步驟 3:隱藏 generator 標籤與 ver= 的版本
<?php
/**
* Plugin Name: Hide WordPress Version
* Description: 隱藏 generator 標籤,以及 CSS、JS 的 ver= 中出現的 WordPress 版本。
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// 將 HTML 的 <meta name="generator"> 與 feed 的 <generator> 清空。
add_filter( 'the_generator', '__return_empty_string' );
/**
* 只有在 CSS、JS 的 ver= 與 WordPress 的版本相同時,才替換成其他的值。
* 因為是替換而不是移除 ver=,所以 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 );
重點如下。
the_generator篩選器,對 HTML 的 generator 標籤與 feed 的 generator 兩者都有效。remove_action( 'wp_head', 'wp_generator' );只會移除 HTML 的標籤,所以對 feed 沒有效果- 如果把
?ver=全部移除,在更新外掛或佈景主題時,瀏覽器可能會繼續使用舊的 CSS、JS。上面的程式碼只在與 WordPress 版本相同的值時,才替換成由版本產生的另一個字串。WordPress 更新後值也會改變,所以快取會被更新 - 外掛或佈景主題自行附加版本號碼的
ver=,不會被更動
儲存之後,請用步驟 1 的指令確認 generator 不再出現,以及 ver= 的清單中沒有殘留 WordPress 的版本。如果使用快取類外掛,請先清除快取再確認。
步驟 4:停用 X-Powered-By 標頭
X-Powered-By 是由 PHP 而不是 WordPress 所附加的標頭,可以從中得知 PHP 的版本。要停用的話,請在 PHP 的設定檔(php.ini)中將 expose_php 設為 Off。這個設定只能在 php.ini 中變更。
expose_php = Off
這是在 VPS 的 Ubuntu 上使用 PHP-FPM 時的範例(8.3 請配合所使用的 PHP 版本)。
# 確認目前的設定
grep -n '^expose_php' /etc/php/8.3/fpm/php.ini
# 改寫之後重新啟動 PHP-FPM
sudo systemctl restart php8.3-fpm
Ubuntu 套件的 php.ini,初始狀態就是 expose_php = Off。如果標頭仍然出現,請確認是否正在使用另一個 php.ini。在日本的租用伺服器上,有些可以在後台的 PHP 設定中變更,有些則無法變更。
無法變更 php.ini 時,也有用 WordPress 程式碼移除標頭的方法。不過 send_headers 是 WordPress 輸出前台頁面時才會執行的掛鉤,所以對後台或登入頁面沒有效果。
add_action( 'send_headers', function () {
header_remove( 'X-Powered-By' );
} );
步驟 5:拒絕存取 readme.html 與 license.txt
readme.html 與 license.txt 是 WordPress 核心的檔案。目前的 readme.html 中沒有寫版本號碼,但可以看出使用了 WordPress。
即使刪除,更新 WordPress 核心之後也會恢復。與其刪除,不如在網頁伺服器上拒絕存取,比較省事。
Apache(.htaccess)的情況
加到 WordPress 資料夾中的 .htaccess。# BEGIN WordPress 與 # END WordPress 之間會被 WordPress 改寫,所以請寫在這個範圍之外。這是 Apache 2.4 的寫法(Order、Deny from all 是 Apache 2.2 的舊寫法)。
<FilesMatch "^(readme\.html|license\.txt)$">
Require all denied
</FilesMatch>
Nginx 的情況
加到網站的 server 區塊,確認設定後重新載入。
location ~* ^/(readme\.html|license\.txt)$ {
deny all;
}
sudo nginx -t && sudo systemctl reload nginx
加入之後執行 curl -s -o /dev/null -w '%{http_code}\n' https://example.com/readme.html,確認會回傳 403。
隱藏仍無法防範的事
- WordPress 的 CSS、JS 檔案內容,每個版本都有些許不同,所以只要取得檔案來比對,就能推測出版本
- 從外掛或佈景主題的
readme.txt或ver=,有時可以得知外掛的版本。容易成為目標的是外掛的漏洞,而不是核心 - 能夠登入後台的人,仍然會和以前一樣看到版本
因此,在隱藏版本的同時,也請進行核心、外掛、佈景主題的更新,刪除不使用的外掛,以及停用後台的檔案編輯等。
總結
- 版本會出現的主要位置,是 HTML 與 feed 的 generator,以及 CSS、JS 的
?ver=。REST API 的/wp-json/不包含 WordPress 的版本 - 用
add_filter( 'the_generator', '__return_empty_string' );就能同時清除 HTML 與 feed 的 generator ?ver=不要移除,只替換與 WordPress 版本相同的值,就不會妨礙快取的更新X-Powered-By以 php.ini 的expose_php = Off停用readme.html即使刪除也會因更新而恢復,所以改在網頁伺服器上拒絕存取- 隱藏只是輔助性的對策,持續更新才是最重要的
相關文章:
- WordPress 安全性標頭的設定方法|.htaccess、Nginx、functions.php 各種做法
- 限制對 WordPress REST API 存取的方法
- 停用 WordPress 佈景主題、外掛檔案編輯器|DISALLOW_FILE_EDIT
對 WordPress 有疑問嗎?本站營運方位於日本,僅以日文回覆。 聯絡我們(日文)