在服務(wù)器的訪問記錄里面看到 wordpress 的?xmlrpc.php?被大量請求,比如下圖:
我甚至碰到過更加過分的情況,有客戶的 wordpress 站點因為?xmlrpc.php?文件被掃描得過多,造成了服務(wù)器負(fù)載過多,進(jìn)入后臺和訪問頁面都變得非常緩慢,并且我們查了好久才知道是這個文件被掃描過多造成的,費事費心費力!
這是因為什么?為什么?xmlrpc.php?文件會被掃描?對于這個問題怎么處理更好。
什么是 XML-RPC
要理解為什么?xmlrpc.php?文件會被掃描,首先要明白什么是 XML-RPC,它的全稱是 XML Remote Procedure Call,即 XML 遠(yuǎn)程過程調(diào)用,它是一套允許運行在不同操作系統(tǒng)、不同環(huán)境的程序?qū)崿F(xiàn)基于網(wǎng)絡(luò)過程調(diào)用的規(guī)范和一系列的實現(xiàn)。
簡單說 RPC 就是通過像本地服務(wù)一樣遠(yuǎn)程調(diào)用另外一臺服務(wù)器上的服務(wù)來完成需求,XML-RPC 就是使用 XML 作為編碼格式的 RPC。
XML-RPC 使用 http 作為傳輸協(xié)議,XML 作為傳送信息的編碼格式,一個 XML-RPC 消息就是一個請求體為 XML 的 http-post 請求,被調(diào)用的方法在服務(wù)器端執(zhí)行并將執(zhí)行結(jié)果以 XML 格式編碼后返回。
一個 XML-RPC 協(xié)議包括兩部分:
RPC client,用來向 RPC 服務(wù)端調(diào)用方法,并接收方法的返回數(shù)據(jù)。
RPC server,用于響應(yīng) RPC 客戶端的請求,執(zhí)行方法,并回送方法執(zhí)行結(jié)果。
wordpress 源代碼(?xmlrpc.php?文件)中已經(jīng)包含了完整的 RPC 服務(wù)端代碼,它支持對文章,媒體,評論,分類,選項等等各方面數(shù)據(jù)的管理。
換句話說,只要懂 XML-RPC 協(xié)議,就可以使用 XML-RPC 對 wordpress 博客的各個方面進(jìn)行操作,也就是說可以使用 XML-RPC 做 wordpress 的客戶端。
XML-RPC 安全隱患
XML-RPC 那么好用,也造成了一定的安全隱患,主要是給攻擊者提供了便利,所以攻擊者的一項工作就是掃描 xmlrpc.php 文件,以便可以實現(xiàn):
1.?XML-RPC pingbacks 攻擊,攻擊者可以利用?XML-RPC 的 pingbacks?方法對 wordpress 實行?DDOS?(分布式拒絕服務(wù))攻擊,如果你使用了 CDN 服務(wù)商的 DNS 保護服務(wù),攻擊者還可以使用?pingbacks?方法獲取站點的真實 IP,剩下不用我說了吧。??
2. 即使 wordpress 設(shè)置了登錄次數(shù)限制,但是使用 XML-RPC 暴力破解 wordpress 的賬號密碼卻逃過了限制,并且 XML-RPC 一次請求就可以執(zhí)行上百次密碼的暴力破解。??
徹底屏蔽 XML-RPC
既然存在這些問題,那么最好關(guān)閉 wordpress 的 XML-RPC 服務(wù),群里面有些小伙伴建議直接刪除 xmlrpc.php 文件就好了,但是刪除了,下次 wordpress 升級之后又會出現(xiàn),不太建議這么做。
最快的方法,只需在當(dāng)前主題的?functions.php?文件添加下面這行代碼就能關(guān)閉它:
add_filter(‘xmlrpc_enabled’, ‘__return_false’);
WPJAM Basic 插件的「優(yōu)化設(shè)置」也有該選項(下圖最后一個),直接勾選即可:
使用 php 代碼或者插件方式關(guān)閉,xmlrpc.php?文件被掃描的時候,整個 wordpress 代碼還是會被加載,所以如果浪費服務(wù)器資源在這上面,可以使用下面方式屏蔽服務(wù)器上?xmlrpc.php?文件的請求:
1. apache 可以通過在 .htaccess 文件前面添加以下代碼:
Order Allow,Deny
Deny from all
這時候訪問 xmlrpc.php,頁面顯示:
2. nginx 服務(wù)器可以添加下面的規(guī)則:
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;
}