幫助中心
這里有最新的使用文檔和教程
修復 WordPress 最大安全隱患,防止 xmlrpc.php 被掃描!
在 WPJAM Basic 的微信群里,經常有小伙伴說,在服務器的訪問記錄里面看到 WordPress 的 xmlrpc.php
被大量請求,比如下圖:
我甚至碰到過更加過分的情況,有客戶的 WordPress 站點因為
xmlrpc.php
文件被掃描得過多,造成了服務器負載過多,進入后臺和訪問頁面都變得非常緩慢,并且我們查了好久才知道是這個文件被掃描過多造成的,費事費心費力!
這是因為什么?為什么 xmlrpc.php
文件會被掃描?對于這個問題怎么處理更好。
什么是 XML-RPC
要理解為什么 xmlrpc.php
文件會被掃描,首先要明白什么是 XML-RPC,它的全稱是 XML Remote Procedure Call,即 XML 遠程過程調用,它是一套允許運行在不同操作系統、不同環境的程序實現基于網絡過程調用的規范和一系列的實現。
簡單說 RPC 就是通過像本地服務一樣遠程調用另外一臺服務器上的服務來完成需求,XML-RPC 就是使用 XML 作為編碼格式的 RPC。
XML-RPC 使用 http 作為傳輸協議,XML 作為傳送信息的編碼格式,一個 XML-RPC 消息就是一個請求體為 XML 的 http-post 請求,被調用的方法在服務器端執行并將執行結果以 XML 格式編碼后返回。
一個 XML-RPC 協議包括兩部分:
-
RPC client,用來向 RPC 服務端調用方法,并接收方法的返回數據。
-
RPC server,用于響應 RPC 客戶端的請求,執行方法,并回送方法執行結果。
WordPress 源代碼( xmlrpc.php
文件)中已經包含了完整的 RPC 服務端代碼,它支持對文章,媒體,評論,分類,選項等等各方面數據的管理。
換句話說,只要懂 XML-RPC 協議,就可以使用 XML-RPC 對 WordPress 博客的各個方面進行操作,也就是說可以使用 XML-RPC 做 WordPress 的客戶端。
XML-RPC 安全隱患
XML-RPC 那么好用,也造成了一定的安全隱患,主要是給攻擊者提供了便利,所以攻擊者的一項工作就是掃描 xmlrpc.php 文件,以便可以實現:
1. XML-RPC pingbacks 攻擊,攻擊者可以利用 XML-RPC 的 pingbacks 方法對 WordPress 實行 DDoS (分布式拒絕服務)攻擊,如果你使用了 CDN 服務商的 DNS 保護服務,攻擊者還可以使用 pingbacks 方法獲取站點的真實 IP,剩下不用我說了吧。?
2. 即使 WordPress 設置了登錄次數限制,但是使用 XML-RPC 暴力破解 WordPress 的賬號密碼卻逃過了限制,并且 XML-RPC 一次請求就可以執行上百次密碼的暴力破解。?
徹底屏蔽 XML-RPC
既然存在這些問題,那么最好關閉 WordPress 的 XML-RPC 服務,群里面有些小伙伴建議直接刪除 xmlrpc.php 文件就好了,但是刪除了,下次 WordPress 升級之后又會出現,不太建議這么做。
最快的方法,只需在當前主題的 functions.php
文件添加下面這行代碼就能關閉它:
add_filter('xmlrpc_enabled', '__return_false');
WPJAM Basic 插件的「優化設置」也有該選項(下圖最后一個),直接勾選即可:
使用 PHP 代碼或者插件方式關閉,xmlrpc.php
文件被掃描的時候,整個 WordPress 代碼還是會被加載,所以如果浪費服務器資源在這上面,可以使用下面方式屏蔽服務器上 xmlrpc.php
文件的請求:
1. Apache 可以通過在 .htaccess 文件前面添加以下代碼:
<Files xmlrpc.php>
Order Allow,Deny
Deny from all
</Files>
這時候訪問 xmlrpc.php,頁面顯示:
2. nginx 服務器可以添加下面的規則:
location ~* ^/xmlrpc.php$ {
return 403;
}
3. 如果以上兩個方式都不好用,還可以在 WordPress 的 wp-config.php
文件最開始的地方添加:
if(strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') !== false){
$protocol = $_SERVER['SERVER_PROTOCOL'] ?? '';
if(!in_array($protocol, ['HTTP/1.1', 'HTTP/2', 'HTTP/2.0', 'HTTP/3'], true)){
$protocol = 'HTTP/1.0';
}
header("$protocol 403 Forbidden", true, 403);
die;
}