WordPress 被駭鑑識實錄 | 拆解四層後門與根除全流程
AI 文章延伸
選擇平台後可直接帶入閱讀脈絡,快速整理重點、補齊盲點,並延伸到同站相關文章。
WordPress 被駭最麻煩的地方,不是清不掉惡意程式,而是清完隔天又長出來。我們接手一個被 Google Safe Browsing 判定為危險的網站,掃描、隔離、換密碼一輪做完,前台乾淨了,結果第二天 /news/ 分類又冒出一批俄文垃圾文,原因很簡單:現代的 WordPress 入侵想要的是長期、隱蔽地佔用你的網站,駭客不會只留一個後門,而是鋪好幾條彼此獨立的復發管道。要真正止血,得先把整條攻擊鏈攤開看清楚。
這篇是一次真實入侵事件的鑑識紀錄,我們會拆解四層持久化後門的運作方式,還原清除流程,並回答那個最多人卡住的問題——為什麼網站被駭清完又中。
症狀:curl 抓到的是乾淨的,瀏覽器看到的不是
第一個線索藏在一個落差裡。用 curl 抓首頁的 HTML,原始碼看起來完全正常,沒有可疑的 <script>,但用瀏覽器打開、看開發者工具的 DOM,卻有一段外部惡意腳本被動態載入了三次。
這個落差本身就是答案。惡意腳本不是寫死在 HTML 裡,而是靠 JavaScript 在瀏覽器端動態注入,專門用來規避只讀原始碼的靜態掃描。單靠 curl 或伺服器端的檔案掃描,你會以為網站是乾淨的,實際上每個真人訪客都被投放了腳本。
鑑識的起手式,跟我們在 用 AI 寫程式安全嗎 那篇談的攻擊者思維其實是同一件事,只是方向相反——不是問「這段程式哪裡寫錯」,而是問「駭客留了什麼能力給自己」。順著這個問題往下挖,四層後門一層一層浮出來。
第一層:寫得比正版還工整的後門 easypost
翻伺服器上最近被修改的 PHP 檔,第一個抓到的是 wp-content/easypost/easypost.php。這個目錄不屬於任何正常外掛,檔案卻有 760 行,程式碼的結構比大多數上架外掛還乾淨。它不透過外掛系統註冊自己,所以你在後台的外掛清單裡永遠看不到它。
真正讓我們停下來的,是它的驗證機制——這個後門對每個進來的請求都要求:
- Token ID 與 request ID
- 時間戳,誤差超過 300 秒直接拒絕
- 請求體的 SHA256 雜湊
- HMAC 簽章驗證
看到這串,做過金流串接的人應該會愣一下——這不就是我們在 API 驗證機制怎麼設計 裡談過的三層防護嗎?Key 驗身分、簽章防竄改、時間戳防重送。駭客把正派工程師用來保護 API 的縱深防禦,原封不動搬來保護自己的後門,目的是不讓資安研究員或其他駭客劫走這個入口。防禦技術本身是中性的,看用在誰手上。
它還帶自我更新能力。update_endpoint 會接收 base64 編碼的 PHP payload,驗證 SHA256、跑完公鑰簽章驗證之後,直接覆寫自己——等於一套帶 OTA 簽章驗證的遠端程式碼更新機制。內建的攻擊功能包括自動發文、注入隱藏外連,隱藏手法從白字、display:none、1px 寬高到 -11407px 位移都有,外連資料存在 easypost_homepage_placements 這個 option 裡,再透過 mu-plugins/easypost-runtime.php 用 ob_start 攔截整個頁面輸出動手腳。mu-plugins(must-use plugins)是 WordPress 會強制載入、且同樣不出現在一般外掛清單的目錄,藏在這裡的東西特別容易被漏掉。
第二層:會把自己藏起來的注入外掛
第二層是一個叫 advanced-database-resolver 的外掛,描述寫著「Automated resource management and cache invalidation handler」,作者掛名「Cloud Starter」,Plugin URI 還指向 wordpress.org,整個包裝成一個人畜無害的快取外掛。
它最狡猾的地方是會自我隱藏。程式裡有一段 str_rot13('nyy_cyhtvaf'),解出來是 all_plugins,它 hook 進這個 filter,把自己從外掛清單裡抹掉,所以就算你逐一檢視後台外掛,也看不到它。
注入邏輯很有針對性:檢查 wordpress_logged_in_ cookie,跳過已登入的使用者;略過 wp-admin、login 頁和靜態資源;只在 wp_footer 用優先權 99 對一般訪客注入腳本。它的 C2 位址經過 gzuncompress 加 base64 兩層混淆,解出來是 https://algo2nest.info/no2x,透過 fetch 拿回 payload,再用 Function 建構式執行。跳過登入者這一手,是為了讓管理員自己瀏覽網站時一切正常,降低被發現的機率。
第三層:把 C2 藏進區塊鏈的盜幣器
第三層 speed-optimizer 用了一個我們第一次在實際案例中遇到的手法:EtherHiding,它的 C2 位址不放在任何一台伺服器上,而是寫進 Polygon 區塊鏈的智能合約(合約位址 0xf5966808a9ECbdb8794F568922809C52b0Fd2446),透過 8 個備援的公開 Polygon RPC 節點用 eth_call 去讀。這樣做的好處對駭客來說很致命——你沒辦法像下架一個惡意網域那樣,去「關掉」區塊鏈上的資料。
它的攻擊對象也經過篩選:檢查 navigator.platform 和 navigator.userAgent,只鎖定 Windows 使用者,並過濾掉 bot、google、spider 這類爬蟲字串。最終 payload 是一個假的 Cloudflare 人機驗證頁,走 ClickFix 社交工程,誘導使用者複製貼上並執行一段惡意指令,目標明確就是有裝加密貨幣錢包的 Windows 使用者。
這一層點出了鑑識的一個現實:攻擊者思維稽核只能涵蓋你「想得到」的攻擊模式。EtherHiding 這種把 C2 藏進區塊鏈的手法,不在任何一份標準檢查清單裡。這也是為什麼偵測不能只靠比對已知的惡意樣式,還得靠檔案完整性監控建立正常基準線,任何偏離都當成可疑。
第四層:潛伏兩年的黑帽 SEO 外掛群
最後一層是五個亂數命名的外掛:laravel-janet、microflex-macroconstant、platformist-quadendpointer 這類。描述全是「monobalance polycompile microsync」這種無意義詞組拼出來的字串,變數名是十幾個英文詞亂拼組成的數百字長字串,每支檔案有十幾處 base64_decode,hook 進 wp_head、wp_footer、template_redirect 對每個訪客注入內容。
它們的建立時間是 2023 年。也就是說,這個網站早在兩年前就被入侵過一次,這批外掛是上一波攻擊留下的持久層,一直沒被清掉。新的攻擊者接手時,等於撿到一個現成的據點。
資料庫裡的入侵痕跡
檔案只是一半,另一半在資料庫。我們用 WP-CLI 撈使用者清單,發現幾個問題:
- 三個惡意管理員帳號:
administrator_47776c、bot(email 是[email protected])、lyra11205,建立時間集中在入侵後幾天內 - 原站主的管理員帳號被拔掉角色,roles 欄位空白、無法登入——駭客一邊建自己的帳號,一邊廢掉原本的管理員
排程和資料污染也很明顯:一個 sc_cron_fetch 的 WP-Cron 定期抓 payload,一個 _transient_sc_payload_t 存著 29KB 的混淆內容,/news/ 分類下塞了 13 篇垃圾文,語言混雜俄文、波蘭文、亞塞拜然文、瑞典文,日期集中在兩天內。
清除流程:一次做完,不能只挑一半
清除的順序很重要,每一步都是一道獨立的防線,這正是縱深防禦的反面應用——駭客靠多層持久化維生,我們就得多層一起拆,抓到一個問題就收手,等於白做。實際執行的順序如下:
- 隔離備份:整站檔案與資料庫先完整備份到隔離目錄,保留證據、也留退路
- 惡意檔案隔離:easypost 後門、三支注入外掛、五個黑帽 SEO 外掛,先停用再搬移,每搬一批就驗證前台正常
- 帳號清理:刪掉三個惡意管理員、轉移其名下內容,恢復原擁有者的帳號角色
- 資料庫清潔:刪掉
sc_cron_fetch排程、清掉_transient_sc_payload_t、移除 13 篇垃圾文 - 核心驗證:跑
wp core verify-checksums,跟官方 checksums 逐檔比對,確認核心檔案沒被竄改 - 憑證輪換:重洗 WordPress salts 讓所有 session 失效、清空登入 session、重設管理員密碼,連資料庫密碼和 SSH 密碼一起換
- 快取清理:清掉 wp-rocket 的頁面快取,再回瀏覽器確認 DOM 乾淨
做到這裡,前台乾淨了,但真正的考驗在第二天。
為什麼清完又中:三條獨立的復發管道
隔天 /news/ 又出現新的垃圾文。這不是沒清乾淨,而是駭客留了三條彼此獨立的後路,我們第一輪只堵到其中一部分。
第一條是後門副本。 wp-content 根目錄下有一個 comment_section_1783218498.php,它不透過任何介面,直接寫資料庫發文,post_author 欄位是 NULL。我們是查 nginx 存取日誌、搜 ?action=create_post 才逮到它的請求。
第二條是應用程式密碼。 一個叫 evptech 的帳號底下掛著兩組應用程式密碼:sentinel 和 auto-bootstrap。這是 WordPress 的官方功能,讓外部程式不用登入密碼就能透過 REST API 操作,攻擊者用它 POST 到 /wp-json/wp/v2/posts 發文。關鍵是,應用程式密碼獨立於登入密碼,你把管理員密碼改一百次,都撤銷不了它——除非你去專門的清單裡把它刪掉。
第三條是根本漏洞。 前面兩條都只是出口,真正的入口是某個舊版外掛的 RCE 漏洞,只要這個洞還在,攻擊者就能重新上傳後門,前面所有清除動作都會被繞過。這個洞不補,網站被駭清完又中就是必然。
這三條管道說明了一件事:清除惡意程式是治標,補掉入侵點才是治本。找不到入口的清除,都是在幫駭客做免費的環境整理。
事後怎麼降低復發:把入侵成本墊高
安全不是一次性的清除,而是把入侵的成本墊高、把發現的時間縮短。針對這次案例,我們給站主的加固清單分成四塊:
- 軟體管理:定期更新核心與外掛,絕不用 nulled(破解版)外掛與主題,有漏洞又無法更新的外掛直接移除(外掛漏洞情報為什麼是接案者的盲點,可參考 AI 寫 WordPress 外掛的三個盲點)
- 帳號安全:定期檢查使用者清單移除不明帳號,盤點應用程式密碼,用不到就把整個功能關掉
- 曝險面控制:關掉 XML-RPC(擋暴力破解與 pingback DDoS)、刪掉會洩漏版本的
readme.html、在wp-config.php加上define('DISALLOW_FILE_EDIT', true); - 偵測與監控:做檔案完整性監控(checksums 或版本控管)、定期跑
wp core verify-checksums、開兩步驟驗證並用高強度密碼
這些措施沒有一項能單獨保證安全,但疊起來,攻擊者要重新進來的成本會高很多,而你發現異常的時間會短很多。這就是縱深防禦真正的意思——沒有一道牆是無敵的,但很多道牆一起擋,就夠讓大部分攻擊者轉去找更好下手的目標。
延伸思考
這篇的結論建立在幾個前提上,值得進一步想:
- 「長期隱蔽佔用」假設攻擊者有長期變現誘因——廣告注入、黑帽 SEO、盜幣的變現鏈成熟,才值得埋這麼多層。若換成勒索軟體,目標剛好相反,是一次性加密加勒索,不追求隱蔽。
- 「補入侵點即治本」假設入口是可定位的技術漏洞——如果入口其實是弱密碼被暴力破解、nulled 外掛本身就帶後門,或同主機其他站橫向感染,那補單一外掛漏洞無效,得改成強化認證、換乾淨來源或處理主機環境。
- 四層後門是多次入侵疊加的結果,不是每個被駭站都長這樣,低調的單漏洞站可能只有一層。
其他領域也有同樣的形狀:
- 潛伏感染——多層持久化後門像帶狀皰疹病毒整合進宿主,停藥(清除)後從潛伏庫復發,治本要清病毒庫而非只壓症狀。
- 安全機制的雙用性——HMAC、簽章、白名單本是防禦工具,卻被後門作者搬去保護自己的 C2 入口,如同加密技術同時保護隱私與勒索軟體。技術中性,決定善惡的是使用者。
常見問題
WordPress 被駭清完又中,是沒清乾淨嗎?
不一定。更常見的原因是還有其他獨立的持久化管道沒堵到,例如藏在根目錄的後門副本、獨立於登入密碼的應用程式密碼,或最根本的——讓駭客能重新上傳後門的外掛漏洞還沒補。只清可見的惡意檔案而不補入口,復發幾乎是必然。
用 curl 看原始碼是乾淨的,為什麼還被 Google 標成危險網站?
因為現代的注入手法多半是靠 JavaScript 在瀏覽器端動態載入惡意腳本,不會寫死在伺服器回傳的 HTML 裡。只讀原始碼的靜態檢查看不到,要打開瀏覽器開發者工具檢查實際渲染出來的 DOM,才會看到被動態注入的腳本。
改了管理員密碼,為什麼駭客還能發文?
如果攻擊者建立了應用程式密碼(Application Passwords),它是獨立於登入密碼的一組憑證,能透過 REST API 操作網站,改登入密碼並不會讓它失效。必須到使用者設定裡的應用程式密碼清單手動撤銷,或直接關閉整個功能。
WordPress 網站被駭,自己處理還是找專業團隊?
若你能操作 WP-CLI、讀伺服器與 nginx 日誌、判斷檔案與資料庫的異常,可以自行按流程清除,但這次案例有四層後門、區塊鏈 C2、多條復發管道,關鍵在於找到根本入侵點——這一步最需要經驗。清不乾淨反而會讓網站持續被列為危險、流量歸零,評估風險後找有鑑識經驗的團隊通常更省成本。
網站被駭,或想在出事前先把 WordPress 的曝險面盤一遍?歡迎聯絡我們,或加入我們的 LINE 官方帳號聊聊你的網站狀況。
Google 偏好來源
喜歡我們的內容嗎?一鍵將我們設為偏好來源,未來在 Google 焦點新聞與 AI 概覽中就能優先看到我們的文章。