網站被掛上賭博轉址、主機商寄來 CPU 異常飆高的警告信、Google 把首頁標成「有害網站」——這些症狀背後,常常不是單一一支惡意檔案,而是攻擊者埋在伺服器裡的 webshell 後門。最折磨人的地方在於:你用安全外掛掃一輪、刪掉看得到的可疑檔案,網站看似恢復,結果 24 到 48 小時後轉址又冒出來。
原因很單純,外掛的掃描範圍多半只在 WordPress 目錄之內,而真正讓你反覆中招的後門,往往藏在 public_html 以外、或偽裝成正常核心檔案,從伺服器層級重新感染你的站。要根治,就得登上伺服器本身,用指令把藏起來的 webshell 揪出來。
這篇談的是 webshell 後門清除的伺服器端做法:怎麼判讀後門特徵、用哪些指令掃描與比對檔案、如何從日誌追出入侵的破口,以及清乾淨之後怎麼在伺服器端把門封死。內容偏向有 SSH 權限、能進 cPanel 或主機管理介面的站長與工程師;如果你手上只有 WordPress 後台,部分步驟需要先向主機商索取存取權限。
為什麼刪掉惡意檔案後網站還是一再被駭?
因為你刪的是「症狀」,不是「入侵點」。webshell 後門的設計目的就是持久化——攻擊者很清楚站長遲早會發現垃圾頁面或惡意轉址並清掉,所以他們會預先埋下一支以上的後門,當作隨時重返的秘密通道。只要漏掉任何一支,攻擊者就能在你清理完的幾小時內,透過瀏覽器存取那個 URL,把惡意程式重新寫回來。
這也是為什麼「重複感染迴圈」是最明顯的警訊。花好幾個小時清完檔案、還原備份,網站看起來正常了,隔天垃圾轉址又出現,幾乎可以確定還有隱藏後門在運作。
一般 WordPress 安全外掛之所以容易漏掉這類後門,有幾個結構性限制。第一、外掛的掃描範圍僅限 WordPress 環境之內,後門若藏在 public_html 之外、或竄改了伺服器設定檔,外掛根本看不到。第二、深度掃描很吃資源,外掛常因 PHP 記憶體限制逾時,攻擊者刻意把後門埋在大型資料夾深處,賭外掛掃到一半就當掉。第三、外掛靠已知惡意特徵比對,攻擊者只要寫一支全新的自訂指令碼,就能繞過特徵庫。
結論是:清後門不能只在應用層做,要把戰場拉到伺服器端,這也是這篇接下來的重點。
webshell 後門長什麼樣?常見特徵與藏匿位置
webshell 是一支放在伺服器上的惡意指令碼,把 HTTP 請求轉成遠端命令通道。攻擊者透過瀏覽器存取它,就能瀏覽檔案系統、上傳更多惡意程式、竊取資料,甚至完全接管主機。它通常以 www-data、apache 這類網頁伺服器使用者的權限執行,對網站根目錄有讀寫與執行的能力。
辨識 webshell,先記住幾個程式碼層面的特徵。後門幾乎不會用明文寫,常見的手法是把惡意邏輯包在這些函式裡:
- 執行類函式:
eval()、assert()、system()、exec()、shell_exec()、passthru()、popen(),把字串當程式碼或系統命令執行。 - 編碼還原函式:
base64_decode()、gzinflate()、str_rot13(),用來把一長串亂碼還原成可執行的程式碼,躲過肉眼檢視。 - 使用者輸入來源:
$_POST、$_GET、$_REQUEST、$_COOKIE、$_FILES,後門靠這些接收攻擊者送來的指令。
最典型的「一句話木馬」就是把執行函式和使用者輸入串在一起,例如把 @eval($_POST['x']); 這一行插進某支正常檔案的開頭或結尾。當執行函式搭配編碼還原、又吃使用者輸入時,幾乎可以斷定是後門。
藏匿位置也有跡可循。攻擊者偏好幾個地方:
- uploads 目錄:
wp-content/uploads本來只該放圖片影片,不該有任何可執行指令碼。站長很少檢查這裡,是後門的熱門落腳處。一旦在按年月分類的圖片資料夾裡看到.php檔,幾乎就是惡意檔案。 - 偽裝成核心檔名:攻擊者會用
wp-options.php、wp-user.php、index-config.php這類看似正常但 WordPress 根本不使用的檔名,藏在根目錄或 wp-includes 裡。 - 注入正常檔案:把後門程式碼直接塞進
wp-config.php、現用主題的functions.php,跟原本的程式混在一起。 - public_html 以外:技術較高的攻擊者會把指令碼放在網站根目錄之外,或竄改伺服器核心設定,這正是應用層外掛掃不到的盲區。
怎麼從伺服器端找出 webshell?指令掃描與檔案比對
最可靠的判斷不是靠人眼翻幾千個檔案,而是「檔案完整性比對」加「特徵字串掃描」兩條路一起走。前提是你能透過 SSH 登入主機,或在 cPanel 終端機下指令。
第一條路、用特徵函式做全站搜尋。把前面那組危險函式丟給 grep,掃出所有可疑檔案再逐一判讀:
grep -rnE "eval(|base64_decode(|gzinflate(|str_rot13(|assert(|shell_exec(|passthru(|system(" /path/to/public_html --include=*.php
要提醒的是,這個結果不全是後門——少數正規外掛也會用到 base64_decode,所以 grep 是「縮小範圍」,不是「定罪」,每一筆都要打開檔案看上下文。重點看:這段程式碼是不是吃 $_POST、$_GET 的輸入?是不是夾在一長串隨機字元裡?是的話就高度可疑。
第二條路、用修改時間找出近期被動過的檔案。你大概知道網站最後一次正常更新的日期,比那個日期還新、又不在你預期內的檔案就要查。例如找出最近 7 天內被修改的 PHP 檔:
find /path/to/public_html -name "*.php" -mtime -7
要注意 webshell 有時會把檔案時間戳改成跟正常檔案一致來規避這招,所以時間比對是輔助,不是唯一依據。
第三條路、跟乾淨版本做差異比對,這是揪出「注入型後門」最有效的方法。從 WordPress 官方下載與你站台同版本的核心檔案,解壓後用 diff 整包對比:
diff -r -q /path/to/public_html /path/to/wordpress-clean
-q 只列出哪些檔案不同、不印內容;確認可疑檔案後再拿掉 -q 細看差異。核心檔案理論上不該有任何差異,凡是被改過的核心檔,要嘛是被注入後門,要嘛該直接用官方版本覆蓋。主題和外掛同理,從官方來源下載對應版本來比對。
如果平常有做檔案雜湊基準,這一步會更快。在網站乾淨時,先把所有檔案算一次雜湊存起來,事發後重算一次比對,就能一次列出新增、被改、被刪的檔案清單。沒有事前基準的話,diff 對乾淨核心就是替代方案。
第四條路、上伺服器級的惡意程式掃描器。比起 WordPress 外掛,在主機上跑 CLI 掃描器不受 PHP 記憶體限制,能掃到應用層之外。常見組合是 ClamAV 搭配 Linux Malware Detect(maldet):
clamscan -r -i /path/to/public_html
maldet -a /path/to/public_html
clamscan -i 只回報命中項目,maldet 則內建專門針對 webshell 與網站後門的特徵。許多 cPanel 主機也整合了 ImunifyAV 這類掃描器,可以一併使用。這些工具是「事後偵測」,幫你找出已存在的問題,不能取代修補漏洞與管理密碼這些根本工作。
四條路交叉比對之後,你手上應該會有一份高度可疑的檔案清單。先別急著刪,下一節先用日誌確認入侵點。
如何從伺服器日誌追出入侵的那支檔案?
伺服器存取日誌是定位後門最直接的線索,因為攻擊者每次操控 webshell,都會在日誌裡留下對那支檔案的請求紀錄。webshell 多半透過 POST 接收指令,所以重點是找「對某支 .php 檔的大量或異常 POST 請求」。
在 cPanel 環境,你能取得幾種關鍵日誌:
- 原始存取日誌(Raw Access Logs):記錄所有訪問的 IP、時間與請求的檔案,用來找出異常 IP 與可疑的檔案請求。
- 錯誤日誌(Error Logs):攻擊者嘗試利用漏洞時產生的錯誤訊息可能留在這裡。
- FTP 存取日誌:判斷是否經由 FTP 管道被入侵、上傳檔案。
實務上,從 access log 裡撈出對 PHP 檔的 POST 請求,再看哪些目標檔名很陌生:
grep "POST" /path/to/access.log | grep ".php"
如果發現大量 POST 都打向某支你沒見過的檔案,例如 uploads 底下的某個 .php,那很可能就是 webshell 本體;而第一次出現該檔案請求的時間點,往往就接近入侵發生的時刻。順著那個時間點往前翻日誌,常能看到攻擊者是透過哪個漏洞、哪次上傳把後門送進來的,這對後面修補破口非常重要。
把日誌追出來的可疑檔案,和上一節掃描出的清單交叉比對,重疊的部分幾乎可以確定是後門。
找到 webshell 後該怎麼安全清除?
清除的順序很重要,順序錯了不是清不乾淨、就是把網站弄壞。下面是相對穩妥的流程。
第一、先完整備份再動手。修改或刪除任何檔案前,先把整個網站目錄與資料庫各備份一份。萬一搜尋過程中誤刪了關鍵系統檔案,這份備份能救回網站。同時,動手刪後門前,建議先把該檔案複製一份留存,方便事後分析攻擊者如何進來。
第二、隔離網站。如果主機商還沒處理,先暫時關閉對外存取,避免攻擊者在你清理期間繼續操控、或感染擴大。在共享主機環境裡,被駭的站若被拿去濫發垃圾信,會連累同主機的其他使用者,主機商通常也會主動強制下線。
第三、刪除確認過的後門檔案。對於 uploads 裡混入的 .php、偽裝核心檔名的假檔案,確認無誤後直接刪除。對於被注入後門的正常檔案,最乾淨的做法是用官方版本整支覆蓋——WordPress 核心與 wp-includes、wp-admin 直接用官方下載版蓋掉,主題和外掛從官方來源重裝對應版本。手動只刪掉被注入的那幾行也可以,但風險高:誤刪一個括號就可能讓網站白屏或噴資料庫連線錯誤,能覆蓋就別手改。
第四、修補入侵破口,這是整個流程裡最關鍵卻最常被跳過的一步。光刪後門不修漏洞,攻擊者會用同一個破口在短時間內再進來。根據前面日誌追查的結果,把當初的入口堵起來:是過時外掛的已知漏洞就更新或移除該外掛、是弱密碼被暴力破解就全面換成高強度密碼、是檔案上傳功能沒驗證就修正驗證邏輯。
第五、若破壞範圍太大、清不乾淨,直接從乾淨備份還原是更快也更可靠的選項,前提是你有一份「確定在感染之前」的備份。要記得還原會覆蓋掉備份時間點之後的所有變更(新文章、訂單、留言),還原前先把這段期間的重要資料另外匯出。還原後務必立刻更新所有程式、改掉所有密碼,否則同一個漏洞還在,很快會再次中招。
除了檔案還要清哪些後門?資料庫、排程與設定檔
只清 PHP 檔案不夠,攻擊者的持久化手段不只藏在檔案裡。下面這幾處沒一起清,後門照樣能復活。
資料庫裡的假管理員帳號。 攻擊者常直接在資料庫埋一個管理員權限的帳號,就算你刪光所有惡意 PHP,他還是能用這組帳密登入後台。從主機控制台進 phpMyAdmin,打開 wp_users 資料表,逐列檢查有沒有陌生的使用者名稱或電子郵件,發現非你建立的就刪掉那一列。
注入資料庫的隱形外掛與內容。 打開 wp_options 資料表,在 option_name 欄位找 active_plugins,有些惡意外掛是直接注入資料庫、不會出現在後台外掛清單裡,編輯這一列、移除陌生的外掛項目。也要檢查有沒有被插入的惡意轉址腳本或垃圾內容。
惡意排程(Cron Job)。 攻擊者會用系統的 cron 或 WordPress 的 WP-Cron 設定排程,定時把後門寫回來——這正是你刪完檔案隔天又中招的常見元兇之一。檢查伺服器的排程設定,移除你不認得、會去抓遠端檔案或執行可疑指令的工作。
設定檔裡的自動載入。 留意 .htaccess(Apache)與 .user.ini,攻擊者可能透過 auto_prepend_file 之類的設定,讓每次 PHP 請求都先載入一支後門。也要檢查 .htaccess 裡有沒有被加上惡意的轉址規則。這些檔案經常被忽略,卻是後門賴以重生的暗門。
把檔案、資料庫、排程、設定檔四個面向都清過一遍,才算真正斷掉持久化通道。
清乾淨後如何在伺服器端封住再次入侵的破口?
清完只是止血,封門才是讓攻擊者進不來的關鍵。伺服器端有幾個動作能大幅墊高再次入侵的成本。
禁止上傳目錄執行 PHP。 uploads 目錄只該放靜態檔案,沒有任何理由執行 PHP。在 Apache 環境,於 wp-content/uploads 放一支 .htaccess,明確擋掉 PHP 的執行;Nginx 則在站台設定裡針對該路徑關閉 PHP 處理。這樣即使攻擊者再次把 .php 丟進 uploads,也無法被當成程式執行,等於廢掉一條常見的後門通道。
收緊檔案與目錄權限。 讓網頁伺服器程序對不該寫入的目錄沒有寫入權限。一般建議目錄權限 755、檔案 644,wp-config.php 收得更緊(如 600 或 640)。權限收緊後,攻擊者就算找到注入點,也較難把檔案寫進核心目錄。
停用危險的 PHP 函式。 如果你的網站用不到 exec、shell_exec、system、passthru 這些可以執行系統命令的函式,在 php.ini 的 disable_functions 把它們關掉。許多 webshell 正是靠這些函式運作,停用後能讓相當一部分後門直接失效。
架一道網站應用防火牆(WAF)。 伺服器端的 ModSecurity,或 cPanel 常見的 CSF,能在請求進到應用之前先過濾掉明顯的攻擊樣式。要分清楚:防火牆擋的是「外部惡意連線」,它無法修補你程式本身的漏洞,也救不了密碼外洩,所以它是多層防護的一層,不是萬靈丹。
全面更新並輪換憑證。 把 WordPress 核心、所有外掛與佈景主題更新到官方最新版,這是堵住已知漏洞最直接的做法;同時換掉 cPanel、FTP、後台、資料庫的所有密碼,並徹底掃描你用來管理網站的電腦與手機——很多入侵的源頭其實是本機中毒、憑證被側錄,網站修好了、本機沒清,駭客照樣再進來。
從發現到封門,伺服器端清後門的節奏怎麼抓?
把整條線收束成一個可執行的節奏:先確認症狀(重複感染、CPU 飆高、陌生管理員),備份後登上伺服器,用 grep 特徵掃描、find 找近期改動、diff 對乾淨核心、再跑一次 CLI 掃描器,四路交叉鎖定可疑檔案;用存取日誌的異常 POST 追出後門本體與入侵時間點;確認後刪檔或用官方版覆蓋,同時清掉資料庫假帳號、惡意排程與設定檔暗門;最後修補當初的破口,並在伺服器端禁掉 uploads 執行 PHP、收緊權限、停用危險函式、輪換所有密碼。
關鍵心法只有一句:清後門的成敗不在你刪了多少檔案,而在有沒有同時堵住入侵點與所有持久化通道。少封一個破口,攻擊者就能從那裡回來。如果評估後發現破壞範圍超出自己能掌握,從乾淨備份整站還原、再做完修補與封門,往往比逐檔清理更省時也更保險;真的清不動,就把站交給專業資安團隊處理,別讓一支沒清掉的 webshell 拖著整個網站反覆中招。