多數網站管理者以為,只要裝一套資安外掛把網站掃過一遍,看到畫面顯示「未發現威脅」,就代表這個網站是安全的。真正處理過入侵案例的人卻清楚,「掃毒」只是眾多防護手段裡的一層,而且它抓得到的東西,跟另一種偵測方式抓得到的東西並不一樣。後者不管檔案內容像不像已知的惡意程式,只在乎一件事,這個檔案跟上一次確認乾淨時比起來,是不是被動過了。這種做法有個正式名稱,叫檔案完整性監控(File Integrity Monitoring,簡稱 FIM)。
它的原理不難懂,先幫每一個檔案算出一組獨一無二的「指紋」,之後定期拿現在的指紋跟乾淨時期留下的指紋比對,只要有一個位元組被改動,兩組指紋就會完全不一樣。它揪出的不只是「內容被改了」,新增一個你沒放上去的檔案,或某個原本該在的檔案憑空消失,同樣逃不過這套比對。對於曾經處理過網站被入侵、卻怎麼也理不清哪些檔案被動過的站主來說,這正是最缺的那一塊拼圖。
WordPress 檔案完整性監控是什麼?
檔案完整性監控是一套比對機制,拿現在的檔案狀態,跟一份確定乾淨的舊記錄逐一核對,只要對不上,就代表這個檔案在這段期間被動過。PCI 安全標準委員會(PCI SSC)在官方詞彙表裡把它定義為「一種變更偵測解決方案,檢查關鍵檔案的變更、新增與刪除,並在偵測到變更時發出通知」,這個定義精準對應了它會盯的三種變化:修改、新增、刪除,不只是「內容被改了」這一種。
雜湊函式將檔案換算成獨一無二的指紋值
整套比對的核心,是一種叫做雜湊函式(例如 SHA-256)的運算方式。把一份檔案丟進雜湊函式,它會吐出一串固定長度的字串,這串字串就是這份檔案的指紋。同一份檔案,不管算幾次都會得到同一組值;但只要檔案裡哪怕只改動一個字元,算出來的指紋就會完全不一樣,而且沒辦法從這組指紋反推回原本的內容寫了什麼。
這個特性讓比對可以在幾秒鐘內做完,不必靠人一行一行肉眼核對程式碼。你的網站動輒上千個檔案,真要靠人工比對每一行程式碼有沒有異動,別說效率低,遇到刻意藏在幾萬行程式碼裡的一小段惡意指令,人眼幾乎不可能發現;但雜湊值只要有一個位元組不同,比對結果就會立刻標記出來,不會因為改動小就被放過。
用第一次比對留下的基準值揪出之後的異動
雜湊值本身沒辦法憑空判斷「這樣正不正常」,一定要有一個對照的對象才有意義。這個對照對象叫做基準值(baseline),在確定網站乾淨的狀態下,把全部檔案算一次雜湊值記錄下來,之後每一次比對,都是拿當下的雜湊值去對這組基準,對不上的才算是異動。基準值只需要建立一次,之後反覆用同一份基準比對即可。

這套「先建基準、再自動比對、再通知」的邏輯,也是美國國家標準暨技術研究院(NIST)在 SP 800-53 資安控制框架裡對完整性驗證的要求方向。SI-7 這項控制條文要求機構「採用完整性驗證工具,偵測軟體、韌體與資訊發生未經授權的變更,並在偵測到未經授權變更時採取對應行動」,底下細分的增強項目更進一步涵蓋在開機、特定事件或固定頻率執行完整性檢查、以自動化工具通知異動、採用集中管理的比對工具,跟定期比對、自動通知這兩個步驟的方向一致。
完整性監控與惡意軟體掃描鎖定的目標不一樣
裝了資安外掛跑完掃毒,你的網站不等於就沒事。掃毒(malware scan)跟檔案完整性監控回答的其實是兩個不同的問題,兩者該一起用,不是二選一。
掃毒比對的是特徵碼,完整性監控比對的是異動
掃毒是拿檔案內容去比對一份已知惡意程式碼的特徵庫,找得到相符的特徵才算命中,能不能抓到東西,取決於特徵庫裡有沒有收錄過這種攻擊手法。完整性監控不管檔案內容像不像惡意程式,只比對現在的指紋跟基準值一不一樣,對不上就示警;NIST 的 SI-7 控制條文也只寫「偵測未經授權的變更」,沒有限定變更要先符合某種已知的惡意特徵。一個問「這是不是壞東西」,一個問「這個東西是不是被動過」。

完整性監控能在特徵碼更新之前先示警
資安廠商得先捕捉到攻擊樣本、分析出特徵,才能把它加進特徵庫,這段空窗期裡,掃毒對新型態的攻擊幾乎沒有反應;完整性監控不需要「認得」眼前的變更,駭客手動改過的檔案、還沒被收錄成惡意特徵的新型後門,只要跟基準值不同就會被標記出來。不過完整性監控示警的只是「有異動」,這個異動是不是真的惡意,仍然需要人工判斷,它不是一套能自動辨識威脅等級的系統。至於掃毒外掛、線上掃描各自天生碰不到哪些地方,又該怎麼搭配著用,屬於掃毒這一側的課題,這裡不再展開。
WordPress 核心檔案比對靠 wp-cli 指令就能做
這套檔案完整性比對,並不是外部資安廠商才有的專利,WordPress 核心專案本身就內建了對應的比對能力,靠一行 wp core verify-checksums 指令就能做。這個指令背後的運作,是向 api.wordpress.org 下載目前 WordPress 版本的官方雜湊值清單,再拿網站上實際安裝的檔案逐一核對;比對通過會顯示「Success: WordPress installation verifies against checksums.」,比對不過則會列出哪個檔案「doesn’t verify against checksum」。這個指令執行時刻意不完整載入 WordPress 本身,因為如果載入過程本身受到已經被植入的程式碼影響,比對結果就不可信了。如果你的網站沒有 SSH 主機權限、也不熟悉命令列,這件事可以請工程師或主機商代為執行,或改用內建同類比對功能、走圖形化介面操作的資安整合外掛,不必自己碰命令列一樣能拿到同樣的比對結果。
核心比對涵蓋的範圍與天生排除的檔案
wp core verify-checksums 比對的範圍,是 WordPress 系統本身的檔案:wp-admin、wp-includes 目錄底下的程式,以及根目錄那些屬於核心程式的 PHP 檔案。這些是官方發行版本就固定存在的檔案,理論上除了升級版本,平常不該有任何變動。
它天生不會、也不該去比對媒體庫裡的圖片影片,也不會去比對 wp-config.php 裡你自己填的資料庫密碼這類客製內容,這些檔案本來就會因為正常使用不斷變動,硬要拿去比對只會製造大量假警報。理解這個範圍界線很重要,核心比對是防護的其中一層,不是全站的完整防護,它負責的是 WordPress 本身有沒有被動過,其他部分要靠別的方法補上。
外掛只有官方目錄收錄的才比對得到
同樣的比對邏輯也可以套用到外掛上,指令是 wp plugin verify-checksums --all(驗證所有已安裝外掛),或指定某一支外掛單獨比對,範例輸出會顯示類似「Success: Verified 8 of 8 plugins.」這樣的結果;加上 --strict 參數,連 readme.txt 這類非程式碼的內容變動也會一併標記出來。佈景主題就沒有這樣的待遇,wp-cli 的雜湊比對指令只有核心與外掛兩種,沒有替佈景主題設計的版本。
不過外掛這邊也有一個容易被忽略的限制,只有發布在 WordPress.org 官方外掛目錄裡的外掛,才有官方雜湊值可以拿來比對。向廠商官網或市集另外購買、沒有上架 WordPress.org 的付費外掛,不少功能比較進階的外掛都屬於這一類,沒有官方雜湊值可用,指令碰到它們只會顯示取不到雜湊值、直接跳過,得靠自己建立基準值的方式補上。
沒有現成基準值時,自己建立檔案指紋比對
外掛只有進了官方目錄才比得到,佈景主題更是連對應的比對指令都沒有,wp-content/ 底下的佈景主題、客製程式碼、還有沒有上架官方目錄的付費外掛,都缺這份可以直接拿來比對的官方雜湊值。這時可以自己動手、或請維運方代為,在網站確定乾淨的狀態下,把這些檔案整批算一次雜湊值存起來當基準,之後定期重算一次跟基準比對,出現差異就代表有東西被改過。這是業界通用的自產基準值比對模式,不是 WordPress 獨有的做法。這麼做最大的差別,是它可以涵蓋佈景主題、自訂程式碼與付費外掛這些官方比對做不到的範圍;代價是需要有人先建立並妥善保存那份乾淨基準,如果基準本身建立時網站就已經被植入東西,之後的比對就沒有意義。實務上,這件事通常交給會寫簡單腳本、或使用整合式資安工具的人來做,一般站主不必自己從零寫比對邏輯。這個做法的正當性,同樣扎根在 NIST SI-7 的控制精神裡,條文只規定採用完整性驗證工具偵測未經授權變更,並沒有限定基準值一定要來自官方發行商,機構或站主自行建立並維護基準值,同樣符合這個控制邏輯;SI-7 底下「集中管理完整性驗證工具」這項增強項目,也只要求工具集中管理,沒有限定工具與基準值的來源。
第一次掃描留下乾淨基準,之後靠比對揪出差異
把自建基準值拆成兩個具體步驟會更好理解。第一步,是在網站剛裝好、確定沒有被動過手腳的狀態下,把檔案內容整批算一次雜湊值存下來,這組值就是接下來所有比對的依據。
第二步,是之後每隔一段時間重新計算一次全部檔案的雜湊值,跟第一步存下來的基準逐一比對,找出不一樣的地方。這個基準只需要建立一次,之後每一輪比對用的都是同一份,不必每次都重新定義什麼叫乾淨。
常異動的目錄要先排除才能減少無謂的假警報
不是每個檔案都適合拿去比對。上傳圖片的資料夾、快取外掛自動產生的暫存檔、記錄網站運作的日誌檔,這類本來就會頻繁正常變動的目錄,如果沒有先排除在比對範圍外,每次比對都會跳出一大串異動。
久了你容易養成看到警報也懶得理會的習慣,反而錯過真正該注意的那一次。這個判斷原則跟前面核心比對天生排除媒體庫是同一套邏輯。wp core verify-checksums 本身就提供 --exclude 參數,讓使用者排除指定檔案不列入比對,這個先排除常異動檔案的設計思路,同樣可以套用到自建基準值的做法上。
完整性檢查工具也有可能被進階攻擊者繞過
裝了完整性監控不代表從此高枕無憂,這套機制也有它的能力邊界,得誠實講清楚。完整性檢查有一個前提,攻擊者沒有能力偽造或清除比對留下的痕跡。一旦攻擊者取得夠高的權限,懂得回頭清理自己改過的檔案,或者連比對結果本身都能竄改,單靠一層完整性檢查就有可能被騙過,這正是為什麼資安建議一律強調多層防護,而不是只依賴單一工具。完整性監控真正該扮演的角色,是提高及早發現的機率,不是保證百分之百攔截。
CISA 揭露的案例,攻擊者曾經騙過完整性工具
美國網路安全暨基礎設施安全局(CISA)與夥伴機關在 2024 年發布的官方資安公告 AA24-060B 裡,記載了一個具體案例,Ivanti Connect Secure 與 Policy Secure 這兩款產品,原廠內建的內部與外部完整性檢查工具(Integrity Checker Tool,簡稱 ICT),在事件應變過程中被證實沒能偵測出已經發生的入侵。CISA 自行進行的獨立研究進一步驗證,這套完整性檢查工具不足以單獨偵測入侵,攻擊者即使在設備執行原廠重置之後,仍可能取得根層級的持續存取權限;鑑識分析也發現,攻擊者會以覆寫檔案、竄改檔案時間戳記等手法清理入侵痕跡,讓設備看起來回到「乾淨狀態」,CISA 據此指出完整性檢查的結果不足以證明設備沒被入侵。
這個案例不是發生在 WordPress 身上,但它示範的能力邊界是通用的,完整性檢查再怎麼完善,面對懂得清理痕跡的攻擊者,都不能單獨扛下全部防線。比較務實的做法,是把完整性監控搭配定期備份、活動記錄、基本的存取控管一起用,不要把所有防護都押在同一套工具上。
比對頻率抓一週一次是業界公認的基準
最實際的問題是,這件事多久該做一次。支付卡產業資料安全標準(PCI DSS)明文給出一個可信的業界基準,PCI DSS 要求 11.5.2 規範受管單位須部署變更偵測機制,例如檔案完整性監控工具,在關鍵檔案發生未經授權的修改(包含變更、新增、刪除)時提醒相關人員,並且要求這套機制至少每週執行 1 次關鍵檔案的比對。多數中小型 WordPress 網站不直接處理信用卡資料,不受 PCI DSS 規範,但至少每週 1 次這個頻率,仍然可以當作一個具體、不空泛的參考基準。
發現異動不必馬上刪除檔案,先隔離保留證據
比對出現異動之後,正確的第一步不是急著把看起來可疑的檔案直接刪掉。先把異動的檔案複製一份保留下來,供後續判斷這是不是誤判,或需要交給人分析攻擊手法用的證據,再考慮隔離或還原。
這個順序呼應前面已經講過的兩件事:完整性監控示警的是異動,不是自動辨識出來的威脅,異動本身不等於惡意;而攻擊者確實有可能刻意清除痕跡。手忙腳亂把可疑檔案刪掉,反而讓後續排查更難進行,先留一份證據,才不會把唯一的線索一起丟掉。
比對紀錄能讓被駭後的清查工作有明確起點
檔案完整性監控真正的價值,不在於它單獨存在,而在於一旦真的發生入侵,先前累積的比對紀錄能直接告訴排查的人,從什麼時候開始、哪些檔案被動過。這讓被駭之後的清查工作有一個明確的起點,不必從幾千個檔案裡大海撈針,一個一個核對。
先把完整性監控建立起來,比對紀錄才有累積的機會,這是被駭之前能做的準備。真正碰上網站已經被入侵、需要動手清查與復原的情境,屬於另一個階段的課題,那時候有沒有這份比對紀錄,會直接決定排查要花幾個小時,還是幾天。
回到最開頭那句話,裝了掃毒外掛,不等於網站就安全。掃毒守的是「認不認得出這是壞東西」,完整性監控守的是「有沒有東西被動過」,兩者疊在一起,才補得齊彼此的破口。從 WordPress 自帶的 wp core verify-checksums 開始,把核心檔案的比對做起來,再視情況決定要不要替 wp-content/ 底下的客製程式碼建一份自己的基準值,固定的比對頻率抓在每週 1 次左右——這幾件事做起來都不複雜,卻是很多網站真正被入侵時,最先派上用場的那份底氣。
