多數討論資安的文章一看到 xmlrpc.php,就直接建議關掉,好像這支檔案本身就是漏洞源頭。真正該問的不是「要不要關」,而是「現在還有誰在靠它運作」。不少網站主直接照抄網路教學把它關掉,幾天後才發現 Jetpack 忽然斷線,後台跳出連線異常,回頭才查出是哪個設定搞的鬼。
XML-RPC 是 WordPress 一支存在超過十年、讓外部程式遠端呼叫網站執行動作的老介面。它能讓手機 App 發文、讓 Jetpack 跟 WordPress.com 保持連線,也正因為能遠端執行動作,資安圈才三不五時把它點名成該關掉的風險項目:被拿去打別的網站、被拿去猜密碼,即使舊漏洞都補了,掃描流量至今仍在敲這支檔案的門。
不過關閉方式不只一種,防護的徹底程度也天差地遠,選錯做法很容易白忙一場、看起來關了其實沒真的擋到什麼,還順便弄斷自己正在用的功能。先搞懂它實際在做什麼、風險出在哪、誰還依賴它,再決定用哪種方式關,才不會兩頭落空。

XML-RPC 是什麼?WordPress 對外溝通的老介面
XML-RPC 全名是 XML-based Remote Procedure Call,是一種透過 HTTP 傳輸、用 XML 格式包裝指令的遠端程序呼叫協定。白話說,它讓一支外部程式可以隔著網路對 WordPress 下指令,叫它去執行某個動作,像是幫忙發一篇文章、上傳一張圖、查一下有哪些分類,不需要人坐在電腦前面登入後台一步步點。WordPress 網站根目錄下的 xmlrpc.php,就是專門接收這種呼叫的入口。
這支介面其實比 WordPress 本身還早出現,源自 WordPress 的前身、b2 部落格軟體那個年代就已經存在。WordPress 早期版本預設是關閉的,使用者要手動到設定裡打開才能用,一直到 2012 年推出的 3.5 版,才把它改成預設啟用。改成預設開啟的主要原因,是讓官方的行動 App 能直接跟網站溝通、遠端發文,不必再讓每個使用者自己先去後台勾選啟用。
依照 WordPress 官方開發者文件的整理,XML-RPC 目前涵蓋的操作範疇相當完整:文章與頁面(含自訂文章類型,3.4 版新增)、媒體檔案(3.1 版新增,包含上傳檔案、讀取單一媒體項目、列出媒體庫)、留言(2.7 版新增)、分類與標籤(3.4 版新增)、使用者(3.5 版新增),還有 pingback 與 trackback 這種通知其他網站連結過來的機制。這套協定不是 WordPress 獨有的設計,官方文件也列出 Ruby、PHP、C# 等多種語言寫成的第三方 XML-RPC 客戶端函式庫,佐證它是一套通用的遠端呼叫介面,只是被 WordPress 拿來當作對外溝通的管道之一。
WordPress 後來把功能更完整的 REST API 整合進核心,兩者一度並存,不少人因此誤以為 XML-RPC 已經被淘汰或移除,但實際上它只是被保留下來的舊介面,不是被拿掉。Jetpack 官方支援文件也明確寫到,WordPress 核心軟體自 3.4 版起就支援 XML-RPC,並且被視為穩定的工具;儘管它的熱度早已不如當年,但因為還有大量既有系統整合它,短期內不會被拔掉。既然沒被移除,那為什麼資安圈三不五時就建議關掉它,關掉之後又會不會動到現有功能,就是接下來要一關一關拆開來看的問題。
資安圈常給的三個關閉理由
XML-RPC 能讓外部程式遠端執行文章、媒體、使用者相關的操作,這個特性本身就是一把兩面刃,設計目的是方便,但對攻擊者來說,同一個入口也代表一條可以遠端下指令的路徑。資安圈常提到的關閉理由,大致可以歸成三種不同的濫用手法,一個比一個更難靠單一修補徹底解決。
第一種是把它拿去打別人,pingback 這個通知對方自己連結過去的機制,被反過來偽造成攻擊第三方網站的跳板。第二種是把它拿去猜自己的密碼,system.multicall 這個原本用來提升效率的方法,被塞進大量帳密組合,一次繞過傳統的登入防護。第三種比較沒那麼戲劇性,卻更貼近多數網站的日常,即使前兩個具體漏洞都已經修補,xmlrpc.php 這支檔案至今仍是掃描機器人長期鎖定的目標,持續消耗主機資源。三者合在一起,其實指向同一個結論。這不是單一漏洞修好就沒事的問題,而是一個歷史悠久、攻擊面本來就比較複雜的端點。

理由一,pingback 曾被用來攻擊第三方網站
Pingback 原本的設計,是讓兩個 WordPress 網站之間可以互相通知:當 A 網站的文章連結到 B 網站,A 會自動送一個 pingback 請求給 B,B 收到後就知道有人連結了自己,通常會在留言區顯示一則通知。這個機制的問題在於,WordPress 在處理 pingback 時,對來源網址這個欄位的驗證並不夠嚴謹。攻擊者可以偽造這個來源網址,讓一個乾淨、正常運作中的 WordPress 網站,代替他去對任意第三方網址發送 HTTP 請求,而不是真的發給發出連結的那個網站。
這個弱點被正式編號為 CVE-2013-0235,美國國家漏洞資料庫的紀錄寫明,WordPress 3.5.1 之前的版本,遠端攻擊者可以透過偽造 pingback 的來源網址,讓 WordPress 網站代為對內網主機發送 HTTP 請求,藉此做連接埠掃描,構成一種伺服器端請求偽造,CVSS 2.0 評分 6.4,屬於中度風險。WordPress 3.5.1 針對攻擊者拿它去掃內網主機這一段做了修補,但攻擊者把同一個機制拿去打外部第三方網站的用法,本質上是功能被濫用,不是單一程式碼漏洞,修補範圍並沒有涵蓋到這一塊。
這個風險不是紙上談兵。2014 年 3 月,國際資安公司 Sucuri 的研究團隊發現,有攻擊者同時操控超過 16.2 萬個真實、乾淨的 WordPress 網站,對單一目標網站大量發送應用層的 HTTP 請求,形成一場分散式阻斷服務攻擊。每個參與攻擊的網站,都是被偽造 pingback 來源網址騙去發送請求,而且每次請求都帶著隨機參數,刻意繞過快取機制,逼伺服器每次都重新載入整個頁面。因為所有攻擊流量都來自真實存在、正常經營的網站,單純用 IP 黑名單很難擋下這種攻擊,國際資安媒體 The Hacker News 當時也同步報導了這起事件,確認攻擊規模與手法。
理由二,system.multicall 一次夾帶上千組密碼
system.multicall 是 XML-RPC 內建的一個方法,原本的設計是讓外部程式一次 HTTP 請求裡打包多個指令,不必為每個動作各發一次請求,對正常串接來說是效率工具。攻擊者反過來利用這個特性繞過暴力密碼防護,一般網站的登入防護,是靠每次登入嘗試各記一筆來判斷有沒有異常,超過幾次失敗就鎖定或要求驗證。攻擊者把上百組甚至上千組帳號密碼包進單一個 system.multicall 請求裡,常搭配 wp.getCategories 這類需要驗證身分的方法去測試帳密是否正確,只要送出 3、4 個 HTTP 請求,就能測試完數千組密碼組合,而網站的登入紀錄上只會留下寥寥幾筆,看起來完全不像正在被暴力破解。
2015 年 10 月,Sucuri 觀測到這類攻擊快速擴大,從 9 月 10 日起就陸續發現這種放大式攻擊流量,到 10 月 7 日當天,請求量已經超過 6 萬次,而且幾乎每個請求裡都夾帶著數百到數千組帳號密碼組合。國際資安媒體 Security Affairs 也獨立報導了同一起事件,確認了這個規模與手法,與 Sucuri 的原始觀測互相佐證。
面對這種放大攻擊,WordPress 4.4 版之後在核心層面做了限制,XML-RPC 伺服器已經規定,單一 system.multicall 請求裡,最多只允許出現一次驗證失敗。這代表 2015 年那種一次請求塞千組密碼的放大手法,在現行版本上已經失效,即使還有人想這麼做,一次請求最多也只能測一組帳密就會被判定失敗。不過這不代表 XML-RPC 從此就高枕無憂,還有一個更難靠單一修補解決的問題,持續留在這支介面上。
理由三,掃描流量至今仍持續消耗主機資源
前兩個關閉理由講的都是曾經發生過、後來被修補的具體攻擊手法,但即使 pingback 的伺服器端請求偽造問題與 system.multicall 的暴力密碼放大都已經在核心層級被堵上,xmlrpc.php 這支檔案並沒有因此被自動化掃描工具放過。它長年被當成攻擊入口,至今仍持續收到大量掃描與嘗試性請求,這些流量本身就會消耗主機的運算資源與頻寬,對資源有限的主機方案來說,光是應付這些雜訊就是額外負擔。更麻煩的是,大量重複的掃描流量,也可能把真正需要留意的異常訊號淹沒在雜訊裡,讓管理者更難第一時間察覺真正的攻擊嘗試。
這不是危言聳聽,而是產業至今仍在因應的現實。WordPress VIP 是 Automattic 官方維運的企業級 WordPress 平台,2026 年 2 月更新的官方文件開頭就寫明,XML-RPC 端點雖然實用,卻也是 WordPress 網站常見的攻擊向量,資安檢視時通常會建議整個關閉。文件也提到,VIP 平台在邊緣層的防火牆與 NGINX 設有速率限制,同一個 IP 位址在 30 秒內對 XML-RPC 端點的請求若超過 10 次,就會被鎖定封鎖 1 小時。一個服務等級這麼高的企業平台,至今仍要替這支端點特別設速率限制,本身就是最直接的證據,即使沒有現行已知的漏洞,這支端點仍持續被高頻率嘗試存取。
先盤點依賴 XML-RPC 的既有功能
搞清楚 XML-RPC 有哪些風險之後,動手關閉前還有一件事更現實,自己的網站現在還有沒有在靠它運作。真正動手關掉之後,才發現某個服務忽然斷線、卻找不到原因,是最常見的翻車情境。最常見的兩種依賴,一種是 Jetpack 外掛透過這個管道與 WordPress.com 建立連線,另一種是行動裝置或桌面發文用戶端,以及少數還沒轉往 REST API 的外部整合工具。判斷方法很具體,檢查外掛清單裡有沒有裝 Jetpack、平常有沒有用手機 App 或桌面軟體發文、有沒有串接會遠端發文或抓資料的第三方服務。只要命中任何一項,關閉前就該先確認替代方案在哪,而不是直接動手關掉再說。
Jetpack 多項功能仍靠這個管道運作
Jetpack 官方支援文件寫得很直接,Jetpack 目前仍需要透過 XML-RPC 驗證才能正常運作。它的做法是讓網站本身變成一個 XML-RPC 伺服器,藉此跟 WordPress.com 建立並維持連線。如果主機防火牆或資安外掛把 xmlrpc.php 整支檔案都擋掉,等於直接切斷 WordPress.com 與網站之間的溝通管道,WP 後台會立刻跳出連線異常的提示,Jetpack 相關功能可能局部失效,也可能整組停擺,官方文件也附上專門排解這類問題的說明頁面。
不過有一個常被忽略的細節值得先弄清楚,Jetpack 走的雖然是 XML-RPC 這條通訊管道,驗證方式卻不是傳統那種帳號密碼明碼傳輸。官方文件說明,Jetpack 用的是類似 OAuth 的權杖簽章機制,產生一組只屬於該次連線的 API 簽章,密鑰只存在使用者網站與 WordPress.com 伺服器之間,就算請求在傳輸過程中被攔截,少了那把密鑰也還原不出實際內容。換句話說,用的是 XML-RPC 不等於一定不安全,真正該看的是實際採用的驗證方式,Jetpack 這個案例的安全性其實跟走 REST API 差異不大,只是通訊管道剛好還是舊的那一條。
行動 App 與部分外部工具,仍可能靠它發布內容
在 REST API 出現之前,XML-RPC 承擔了 WordPress 對外溝通的大部分工作,官方行動 App 靠它遠端發文,在 3.5 版之前,使用者甚至得先手動打開這個功能,App 才能用;桌面部落格用戶端靠它同步內容;還有一些跟其他部落格系統或服務對接的場景,也是走這條路。REST API 整合進核心之後,前面這幾種角色大多逐步轉往功能更完整的 REST API。但這裡有個例外情況要老實講清楚,如果網站還在使用低於支援 REST API 版本的 WordPress,或是串接的第三方應用程式還沒升級成支援 REST API,那一條溝通路徑目前仍舊需要靠 XML-RPC 才能運作,並不是所有整合都已經切換完畢。
另外還有一個 2020 年才出現的過渡機制值得提一下,應用程式密碼。WordPress 5.6 版起,官方把應用程式密碼列為讓桌面、行動用戶端與第三方服務對 WordPress 做 API 驗證的建議做法,讓這些用戶端不必再儲存使用者本人的主要登入密碼。這種密碼一樣可以直接用在 XML-RPC 的驗證上,取代帳號原本的密碼。這個設計本身也代表官方其實承認一件事,目前仍處於部分行動或整合工具還沒完全脫離 XML-RPC 的過渡階段,還不到已經切換完畢的地步。也因為有這個工具存在,關閉 XML-RPC 除了開與關兩個選項之外,還多了一條折衷的路。
三種常見做法,防護程度不一樣
確認完自己的網站還有誰在依賴 XML-RPC 之後,才輪到怎麼關這件事。網路上教學大多把關閉 XML-RPC 講得像同一件事,但實際上這三種常見做法動手的層級不一樣,防護的徹底程度也天差地遠。外掛或程式碼濾鏡是在 WordPress 應用程式層攔截,擋下的只是需要驗證的方法,pingback 這類不需要驗證的端點其實還在運作;伺服器層的 .htaccess 或 NGINX 規則,是在請求還沒交給 WordPress 處理之前就先擋掉,防護與效能都更徹底;還有一種更精細的做法,不是整支關掉,而是只允許用應用程式密碼驗證 XML-RPC 請求,把明碼帳密可能被暴力猜測的攻擊面收斂掉,同時保留 Jetpack 或其他仍依賴這條管道的工具繼續運作的空間。

程式碼濾鏡只擋掉需要認證的方法
網路上大量教學都把 add_filter( 'xmlrpc_enabled', '__return_false' ); 這行程式碼,當成完全關閉 XML-RPC 的標準做法。但依照 WordPress 官方 Hook 參考文件,這個 filter 的實際作用跟字面聽起來的不太一樣,它並不是控制 XML-RPC 整支介面是否啟用,而是只控制需要驗證的方法是否啟用,例如發文這類動作;文件也明確註明,這個 filter 不會影響 pingback 或其他不需要驗證的自訂端點,這是預期中的行為,不是漏掉沒處理。
換句話說,裝上這種濾鏡之後,xmlrpc.php 這支檔案本身依然存在,只是呼叫需要驗證的方法時會失敗,拒絕執行。市面上那些安裝即用、不需額外設定的停用類外掛,本質上也是在同一個層級攔截,效果跟自己寫這行濾鏡是一樣的。這種做法能有效防住 system.multicall 那種暴力密碼放大攻擊,因為那些方法本來就需要驗證身分;但防不了 pingback 被拿去攻擊第三方網站的用法,因為 pingback 根本不需要驗證,擋的規則完全碰不到它。如果關閉的目的就是要防堵這一塊,選這種做法從一開始就沒有真正達到目的。
伺服器層直接擋下連線,防護與效能都更徹底
伺服器層的做法,是在 .htaccess(Apache 主機)或 NGINX 設定裡直接寫規則,在請求還沒交給 WordPress 處理之前,就先把它擋下來。因為連線在最外層就被中斷,pingback 這種不需要驗證的方法也會一併被擋掉,防護範圍比程式碼濾鏡完整得多,對伺服器效能的負擔也更小,因為請求根本不會進到 WordPress 去跑一輪。以 Apache 主機為例,一段常見的 .htaccess 規則寫法是這樣:
<Files xmlrpc.php>
order deny,allow
deny from all
allow from 123.123.123.123
</Files>Code language: Apache (apache)
上面這段規則的意思是,先拒絕所有來源,再放行 allow from 那一行指定的 IP 位址,等於只留一組固定 IP,例如公司或自己家裡的網路,能繼續存取 xmlrpc.php,其餘一律擋下。如果不需要留任何例外,把 allow from 那一整行刪掉就好,變成完全封鎖。國際 WordPress 教學媒體 WPBeginner 也提醒,設定完之後別只憑感覺,直接用瀏覽器打開自己網站的 xmlrpc.php 網址確認,如果規則生效,應該會看到拒絕存取的錯誤訊息,而不是 XML-RPC 原本的正常回應。另外也有部分主機服務商,會在偵測到攻擊流量時,主動在伺服器層直接封鎖 xmlrpc.php,自己動手修改設定之前,值得先確認主機商是不是已經處理過這一塊,免得重複設定。
應用程式密碼是取代整支關閉的折衷做法
除了開跟關之外,還有一種不是二選一的折衷做法,只允許用應用程式密碼驗證 XML-RPC 請求,而不是把整支功能關掉。應用程式密碼是綁定特定使用者帳號、專門給 API 驗證用的憑證,由 24 個字元組成,可以針對個別用途各別撤銷,而且不能拿來登入 wp-admin 後台,只能用在 API 驗證的場景。做法上很直接,把這組密碼直接套進 XML-RPC 請求裡,取代帳號原本那組登入密碼即可,既不必動用戶端的設定邏輯,也不再有明碼密碼被暴力猜測的風險。
WordPress VIP 現行的做法,正好是這種思路的具體示範。這個由 Automattic 官方維運的企業級 WordPress 平台,對 XML-RPC 提供三種分級授權模式:進階安全模式只允許 Jetpack 發出的請求,其餘 XML-RPC 請求一律擋下;預設模式規定 XML-RPC 請求只能用應用程式密碼驗證;基本模式則放寬到應用程式密碼、或未開啟兩步驟驗證帳號的帳密都能拿來驗證,安全性相對較低。文件也提醒,直接用程式碼把 XML-RPC 關掉,常常會連帶弄斷 Jetpack 的連線,而透過這種分級授權的設定方式,Jetpack 的連線反而能維持正常運作。對一般網站來說,這個案例給出的思路很清楚,關閉與否從來不是唯一選項,中間還有限制驗證方式這一條路可以走。
關閉後的驗證步驟與常見誤區
不管最後選了哪一種做法,關閉之後不能只憑感覺覺得應該有生效,而是要實際確認回應內容,並且回頭看看原本依賴這條管道的工具,連線狀態有沒有出現異常。這裡也是最容易被忽略的一步,很多人只驗證有沒有裝外掛、有沒有加那行程式碼就覺得大功告成,卻沒發現程式碼濾鏡從一開始就沒擋住 pingback。

瀏覽器或線上工具都能比對回應內容
最直接的驗證方式,是直接在瀏覽器打開自己網站的 xmlrpc.php 網址,比對回應內容判斷目前的狀態。如果 XML-RPC 沒做任何處理,正常情況下這支檔案會回應一段文字,說明這支服務只接受 POST 方法呼叫,代表它仍在正常運作;如果是被伺服器層擋下,應該會看到拒絕存取的錯誤訊息,而不是代表設定寫錯的伺服器內部錯誤,兩者要分清楚,才不會把正常的封鎖結果誤判成設定失敗。
除了手動測試,也可以用線上的 XML-RPC 檢測服務,直接輸入網域,測試 xmlrpc.php 目前是不是還能回應請求,結果通常會直接標示已啟用或已停用,比自己肉眼比對回應內容更明確。國際主機服務商 Kinsta 官方部落格就示範過同一個網站在裝上停用類外掛前後的對照,檢測結果從已啟用變成已停用,可以當作驗證是否生效的參考做法。
程式碼濾鏡關掉的假象,最容易被忽略
前面提過,程式碼濾鏡只會停用需要驗證的方法,pingback 這類不需要驗證的端點並不受影響。這件事在驗證階段特別容易被忽略,很多人只測試 system.multicall 這類需要驗證的方法能不能被呼叫,測不通就以為整支 XML-RPC 都已經關掉,卻沒有另外確認 pingback 相關功能是不是也一併停用。如果原本關閉的目的就是為了防堵 pingback 被拿去攻擊別的網站,這種只做半套的驗證方式,從頭到尾都沒有真正達到目的,得額外確認 pingback 相關端點,或是乾脆換成伺服器層的擋法。
另一個方向反過來也一樣重要,如果選擇的是伺服器層整支擋掉 xmlrpc.php,驗證清單裡一定要包含回頭確認 Jetpack 或其他原本依賴的工具,連線狀態是不是還正常。WordPress VIP 官方文件也提到,若透過程式碼手動關閉或限制 XML-RPC,經常會連帶弄壞網站與 Jetpack 的連線功能,即使 XML-RPC 被停用,像 Jetpack Search 這類仍需要維持運作的功能,一旦連線斷掉,查詢就會退回直接打資料庫,拖慢網站效能。這正好呼應前面盤點依賴那一段的判斷結果,關掉之前先確認自己還有誰在用,關掉之後再回頭驗一次那些依賴還好不好,這一步不能只做一半。
XML-RPC 這支介面留到現在,不是因為沒人管,而是因為背後牽動的東西比想像中多。它確實有實際發生過的攻擊案例撐腰,值得認真看待;但它也還撐著 Jetpack、部分行動用戶端與少數還沒轉往 REST API 的整合工具,不是關掉就一定比較安全,也不是留著就一定有風險。真正該做的判斷,從來不是網路上教學怎麼寫就照著關,而是先弄清楚自己的網站現在依賴到哪裡,再挑一種跟這個依賴程度對得上的做法,關完之後也花一分鐘確認回應內容跟原本的功能都還正常。這件事本身沒有捷徑,但也沒有想像中複雜,願意花這幾分鐘查清楚,就已經比多數只照抄一行程式碼的做法,更接近真正該有的防護。
