WordPress XML-RPC 該不該關?停用設定全解

如果你翻過自己網站的存取紀錄,很可能看過這個畫面:來自世界各地的 IP,一天 24 小時不停往 /xmlrpc.php 灌 POST 請求,每一筆都夾帶不同的帳號密碼。這不是流量暴衝,是有人正拿 WordPress 的 XML-RPC 介面當後門在試你的密碼。問題是,這個介面從 WordPress 3.5 版起就預設開啟,多數站長根本不知道它存在,更別說關掉。

XML-RPC 曾經是 WordPress 對外溝通的主要管道,但這個角色早就被 REST API 接手。留著它,對絕大多數網站來說沒有功能上的好處,只是多開了一道對外的攻擊面。這篇會把 xmlrpc.php 的攻擊原理講清楚,幫你判斷自己的站到底該不該關、關之前要先確認哪些相容性,並給出從外掛到伺服器層的完整停用設定與驗證方法。

XML-RPC 是什麼,為什麼 WordPress 預設還開著

XML-RPC 是一套讓外部程式遠端呼叫 WordPress 功能的介面。它用 HTTP 當傳輸協定、用 XML 當資料格式,對外的進入點就是網站根目錄下的 xmlrpc.php。外部應用程式對這個網址送出一段 XML 訊息,告訴 WordPress 要做什麼,例如發布文章、抓留言、登入驗證、送出 pingback,WordPress 解析後執行,再回傳一段 XML 結果。

這套規範比 WordPress 還早出現。它原本存在於 2003 年被 fork 成 WordPress 的 b2 部落格軟體裡,從 WordPress 誕生起就一直帶著。早期它負責的事不少:讓桌面發文軟體和手機 App 不必登入後台就能發文、串接 Blogger 與 Movable Type 之類的外部平台、支撐 trackback 與 pingback,也是 Jetpack 連回 WordPress.com 的橋樑。

預設開啟這件事,要回溯到 3.5 版。在那之前 XML-RPC 預設是關的,使用者得自己手動打開;3.5 版改為預設啟用,主要動機是讓當時的 WordPress 手機 App 能直接跟站台溝通。問題在於,從 4.4 版把 REST API 併進核心之後,上述這些對外溝通幾乎全部改走 REST API,XML-RPC 的任務基本上結束了。它之所以還留在核心裡沒被移除,純粹是 WordPress 對向後相容的堅持,要照顧那些無法升級、仍依賴舊介面的老站。

換句話說,對一個正常更新的現代站台來說,xmlrpc.php 是個沒在工作卻一直開著門的端點。

xmlrpc.php 會打開哪些攻擊面

xmlrpc.php 的危險不在於它「可能有漏洞」,而在於它的設計本身就替攻擊者省了力。它公開、不需要先進後台就能存取,而且支援把多個指令打包進一個請求,這幾個特性湊在一起,讓它成為自動化攻擊的熱門目標。具體有三條攻擊路徑。

第一條是繞過鎖定的暴力破解。 正常情況下,針對 wp-login.php 的登入嘗試會被防火牆或安全外掛盯著,連續失敗幾次就鎖 IP。XML-RPC 提供一個叫 system.multicall 的方法,原本是給開發者把多個指令合併成一次請求用的,攻擊者卻拿它把成百上千組帳密塞進單一一次 POST。本來要送 500 個請求才試得完的密碼,現在一個請求就試完,而且因為走的不是登入頁,傳統「監看登入頁失敗次數」的防護根本看不到。就算每一組都猜錯,伺服器仍要花 CPU 去解析那包 XML、逐一驗證帳密、再回傳結果,光是被掃就會吃掉資源。

第二條是 pingback 反射式 DDoS。 pingback 原本是「別的站連到你的文章時通知你」的功能,但這個協定缺乏來源驗證。攻擊者可以偽造目標網站的位址,對成千上萬個開著 pingback 的 WordPress 站送出請求,要這些站全部去 ping 同一個目標。每一個被利用的站都會乖乖回應,瞬間湧向目標的大量流量就形成了反射式攻擊。這種攻擊難以靠封 IP 擋下,因為流量來自一大票真實的伺服器。值得注意的是,受害的不只是被打的那個目標——你的站如果開著 pingback,等於隨時可能被當成攻擊別人的跳板,自己也跟著耗資源、背上協助攻擊的責任。

第三條是破門之後的後門植入。 前兩條偏向消耗資源,真正致命的是 multicall 暴力破解一旦猜中管理員帳密。攻擊者拿到後台控制權後,第一步通常是植入隱藏的後門程式,靠這個持久存取點投放惡意程式碼、竄改核心檔案,或把你的自然流量導去惡意網域。這時候已經不是效能問題,是整站被接管的資安事件。

怎麼判斷自己的站有沒有開、有沒有被打

確認 XML-RPC 是否啟用,不能只看檔案在不在。xmlrpc.php 是每個 WordPress 安裝都有的核心檔,就算功能被停用,檔案本身還是在。要看的是它對請求有沒有回應,有三種查法。

瀏覽器直接開。 在網址列輸入你的網域加上 /xmlrpc.php。如果畫面只回一行「XML-RPC server accepts POST requests only」,表示這個端點是開著且作用中的;如果看到 403 Forbidden 或 404 Not Found,代表伺服器已經擋掉存取。

用 curl 送請求測。 在終端機下這行,把網域換成你自己的:

curl -d "system.listMethods" https://yourdomain.com/xmlrpc.php

如果端點是開的,伺服器會吐回一段列出可用方法的 XML;要是已經擋掉,會回 403 或 404。

翻存取紀錄找攻擊跡象。 真正要警覺的訊號,是紀錄裡出現大量針對 /xmlrpc.php 的 POST 請求、單筆請求體積特別大(multicall 包很多帳密的徵兆),或同一個 IP 在短時間內爆量送請求。這類自動化的暴衝往往是暴力破解正在進行的前兆。實務上很多站長是先裝了 Wordfence 這類安全外掛、在即時監控裡看到 xmlrpc.php 被全球各地的主機 24 小時輪番嘗試登入,才意識到問題。

關掉之前先確認的相容性清單

對多數網站來說停用 XML-RPC 不會有任何感覺——你照樣登入後台、寫文章、裝外掛,這些都走後台或 REST API,跟 xmlrpc.php 無關。但停用前還是該花一分鐘確認,你有沒有正在用以下這些少數仍依賴它的服務,免得關了之後某個整合悄悄壞掉。

  • Jetpack 外掛:較舊版本的部分功能透過 XML-RPC 連回 WordPress.com,雖然新版多已改走其他機制,若你重度依賴 Jetpack,停用後要實測各項功能是否正常。
  • 舊版官方 WordPress App 或第三方發文工具:透過遠端發文的桌面客戶端、或某些自動化發文服務若是走 XML-RPC 而非 REST API,會在停用後斷線。
  • 依賴 pingback、trackback 的工作流程:如果你刻意保留站際引用通知,全面停用會一併關掉這部分。

確認的方法很單純:如果你沒在用上面任何一項,或這些工具都已支援 REST API,就可以安心全面停用。真有無法升級又非走 XML-RPC 不可的老舊整合,正確做法是更新那個應用程式或換成支援 REST API 的替代品,而不是為了它一直開著整個端點。

停用方式怎麼選

停用 XML-RPC 有外掛、程式碼過濾器、伺服器層封鎖三類做法,差別在於「擋的位置」。位置越前面,越能在 WordPress 跑任何程式碼之前就把請求擋掉,省下伺服器資源。以下由淺入深。

用外掛停用最省事但最佔資源

最簡單的做法是裝一支專門外掛,例如 Disable XML-RPC,啟用後它會自動停用 XML-RPC 的方法。要提醒的是,這類外掛多半只停用功能、不阻擋連線,所以裝完用瀏覽器開 /xmlrpc.php 仍連得上,但實際呼叫服務時會回錯誤。缺點是為了單一功能多裝一支外掛,會替每次頁面載入增加額外負擔,站台外掛一多就拖慢效能。

用過濾器停用不必裝外掛

如果不想多裝外掛,可以用 WordPress 內建的 xmlrpc_enabled 過濾器關掉它:

add_filter( 'xmlrpc_enabled', '__return_false' );

雖然可以塞進佈景主題的 functions.php,但更穩妥的做法是寫成一支站點專屬的小外掛,因為改主題或換主題時 functions.php 的修改會跟著消失。要注意這個過濾器跟外掛一樣只停用方法、不阻擋連線,請求還是會進到 PHP 才被擋下,省不了被掃時的解析成本。

在伺服器層封鎖最徹底

要真正在 PHP 執行前就擋掉請求,得從伺服器設定檔下手,這也是面對大量攻擊時最省資源的做法。動手前務必先備份設定檔,少一個括號或語法放錯位置,就會立刻觸發 500 錯誤讓整站離線。

Apache(2.4 以上,台灣多數 cPanel 虛擬主機屬於這類)在網站根目錄的 .htaccess 加上:

<Files "xmlrpc.php">
Require all denied
</Files>

若是較舊的 Apache 2.2 環境,則改用舊語法:

<Files "xmlrpc.php">
Order Deny,Allow
Deny from all
</Files>

Nginx(常見於 VPS 與雲主機)沒有 .htaccess,要在 server 區塊加入下列設定,再執行 nginx -t 測試語法無誤後重載服務:

location = /xmlrpc.php {
deny all;
access_log off;
log_not_found off;
}

IIS 主機則是在 WordPress 根目錄的 web.configipSecurity 限制存取,把允許清單留給本機或你自己的 IP,其餘一律拒絕。

如果你的站掛在 Cloudflare 這類 CDN 後面,還有一個更前置的位置可以擋:在 Cloudflare 的防火牆規則裡,把請求路徑等於 /xmlrpc.php 的流量直接封鎖或挑戰。好處是惡意請求在抵達你的主機之前就被擋在邊緣節點,連伺服器頻寬都省下來。

想保留部分功能時的折衷做法

不是每個站都要全有或全無。如果你確實還需要 XML-RPC 的某些能力,但又想壓低風險,有兩種折衷路線。

第一種是只關掉 pingback、保留其他方法。pingback 是反射式 DDoS 的根源,也是多數站根本用不到的功能,單獨關掉它就能消掉一大塊風險,又不影響其他遠端整合。這類「只停 pingback」可以靠專門外掛達成,或在程式裡移除 pingback 相關的 XML-RPC 方法。要注意的是,伺服器層的封鎖(Nginx 的 deny all、Apache 的 Require all denied)是整檔封鎖,沒辦法只擋單一方法;要做到方法層級的細選,得靠應用層設定或 WAF 規則。

第二種是限定來源 IP。如果只有少數固定位置會用到 XML-RPC,可以在 .htaccess 或 IIS 設定裡只放行你自己的 IP、其餘全擋,這樣端點對外界仍是關閉的,卻保留你需要的通道。Web 應用程式防火牆(WAF)在這方面也很有效,許多 WAF 與安全服務預設就把 XML-RPC 流量擋掉或限流,能在請求進到主機前先過濾掉惡意連線、攔下機器人。

停用後務必驗證,並別忘了 REST API 是另一道面

改完設定不要假設它生效了,一定要實測。最常見的失誤就是設定看似套用、端點其實還在收 POST 請求。

最快的查法是再用瀏覽器開 /xmlrpc.php:看到 403 Forbidden 或 404 Not Found,代表伺服器層已經擋住;若還是回「XML-RPC server accepts POST requests only」,表示檔案仍可存取、WordPress 還在回應,你還沒真正擋掉。想更精確就下 curl -I https://yourdomain.com/xmlrpc.php 看回應狀態碼,目標是 403 或 404。最後回頭翻存取紀錄,停用生效後就不該再看到來自隨機 IP、尤其是成批且自動化的成功 POST 請求。

還有一個容易被忽略的觀念:關掉 XML-RPC 不等於 REST API 也安全了。這兩個是各自獨立的對外介面,停用 xmlrpc.php 完全不會影響 REST API。REST API 同樣會被列舉使用者、被探測端點,需要另外做存取控制與監控。把 XML-RPC 當成解決資安的單一開關,會讓你忽略了還開著的另一道門。

該不該關,其實答案很明確

對絕大多數正常更新、靠後台和 REST API 運作的 WordPress 站台,xmlrpc.php 是一個沒在做事卻持續暴露在外的端點,關掉它能直接削掉暴力破解與 pingback 反射這兩條最常見的攻擊路徑,幾乎沒有副作用。真要保留,也該縮到「只開需要的方法、只放行需要的 IP」,而不是整個敞著。

先用瀏覽器或 curl 確認你的站現在是不是開的,對照相容性清單確定沒有正在用的整合會被影響,再依你的主機環境選一種停用方式——能在伺服器層或 Cloudflare 邊緣擋掉就別只靠外掛。改完記得回頭驗證狀態碼,順手把 REST API 的存取控制與登入防護一起檢視一遍。把這道老舊的門關好,你的站台攻擊面就少了一塊長期被忽略的破口。

相關文章
標籤: 暴力破解, WordPress, XML-RPC, xmlrpc.php, 網站資安