WordPress 惡意程式碼 SSH 掃描指令大全:找出被植入的後門

這篇需要 SSH 操作

這篇文章的操作需要透過 SSH 連進伺服器執行。還不熟悉 SSH?請先看SSH 連線教學。

備份做完了。接下來要搞清楚攻擊者在你的網站裡塞了什麼。

這一步的重點是只掃不清。先把所有感染點全部找出來,列成清單,之後再一次清乾淨。邊掃邊刪會讓你漏掉互相關聯的後門。

以下所有指令都是 SSH 進伺服器後直接跑的。範例路徑用 /home/runcloud/webapps/SITENAME,請替換成你的實際網站目錄。


先看 index.php 有沒有被動過

WordPress 的 index.php 是所有前台請求的入口,也是攻擊者最愛動手腳的地方。正常內容只有三行:

<?php
define( 'WP_USE_THEMES', true );
require __DIR__ . '/wp-blog-header.php';

用 cat -n 打開來看行號:

cat -n /home/runcloud/webapps/SITENAME/index.php

超過十行,或出現 goto、eval、base64_decode、一堆看不懂的變數名——那就是被植入了。


全站惡意程式碼掃描

下面這組指令從五個角度掃。整段複製貼上,一次跑完:

cd /home/runcloud/webapps/SITENAME

echo "=== 含 eval + base64 ==="
grep -rl "eval.*base64_decode\|base64_decode.*eval" --include="*.php" . 2>/dev/null

echo "=== 含 goto 混淆 ==="
grep -rl "goto [a-zA-Z0-9_]\{10,\}" --include="*.php" . 2>/dev/null

echo "=== 含可疑函數 ==="
grep -rl "str_rot13\|gzinflate\|gzuncompress\|assert(" --include="*.php" . 2>/dev/null

echo "=== 根目錄下的非標準 PHP ==="
find . -maxdepth 1 -name "*.php" ! -name "wp-*" ! -name "index.php" \
  ! -name "xmlrpc.php" ! -name "license.php" | head -30

echo "=== 最近 3 天內被修改的 PHP ==="
find . -name "*.php" -mtime -3 -not -path "./wp-content/cache/*" | head -50

每段在掃什麼

  • eval + base64:最經典的惡意程式碼寫法。攻擊者把實際程式碼用 base64 編碼,執行時再解碼跑 eval()。正常的 WordPress 外掛極少這樣寫。
  • goto 混淆:用大量 goto 跳轉把程式碼打亂,讓人看不懂。後面接超長隨機標籤名(10 字元以上)是明確的混淆特徵。
  • 可疑函數:str_rot13 做字元旋轉、gzinflate / gzuncompress 做壓縮解壓、assert() 可以當 eval() 用。正常外掛出現這些的機率很低。
  • 根目錄非標準 PHP:WordPress 根目錄下合法的 PHP 就那幾個(wp-*.php、index.php、xmlrpc.php)。其他的像 hiroshi.php、item.php,幾乎都是後門。
  • 最近被修改的 PHP:你最近沒動過程式碼,但有 PHP 檔案在 3 天內被改過——那很可能是攻擊者的手筆。排除 cache/ 目錄是因為快取外掛會正常產生 PHP 快取檔。

掃描結果怎麼讀

  • 空結果 = 該類型沒命中,是好事。
  • 命中的檔案路徑會列出來,先記下來,之後統一處理。
  • 在 wp-includes/ 裡命中不一定是惡意的——WordPress 核心的 HTML parser 確實用了 goto。用 cat 打開看內容再判斷。

檢查檔案有沒有被鎖

有些惡意程式會用 Linux 的檔案屬性保護自己。設了 immutable 旗標之後,就算是 root 也不能直接刪除或覆寫:

lsattr /home/runcloud/webapps/SITENAME/*.php
lsattr /home/runcloud/webapps/SITENAME/wp-includes/*.php | grep "\-i\-"

輸出裡看到 ----i--------- 帶 i 的,就是被設了 immutable。解除方法:

chattr -i 檔案路徑

另外也要注意 ACL。如果 ls -la 輸出的權限欄尾巴有個 + 號,代表有額外的 ACL 規則。清除方法:

setfacl -b 檔案路徑

掃完之後要注意的事

不是所有命中都是惡意的

有些合法外掛確實會用到 base64_decode(處理圖片、解碼授權金鑰)。掃到命中的檔案,一定要用 cat 打開看一下再判斷。

判斷準則很簡單:看得懂程式碼在做什麼的,可能是正常的;通篇都是亂碼變數名和編碼字串的,是惡意的。

掃描結果存下來

建議把掃描結果導到檔案,方便之後對照:

上面那整段掃描指令 > /tmp/scan-result-$(date +%Y%m%d).txt 2>&1

清完之後再跑一次同樣的掃描,跟第一次的結果比對,確認沒有漏掉。

惡意程式不斷自動出現怎麼辦

你刪了一個檔案,過幾分鐘同名檔案又出現了。

這代表有一個還活著的 PHP-FPM worker 在即時執行惡意程式碼,不斷把後門寫回來。遇到這種狀況,先不要繼續掃——直接跳到清除階段的「停掉 PHP-FPM pool」步驟,斷掉它的執行環境再回來掃。

這些指令只掃 PHP 檔案

惡意程式有時候會偽裝成 .ico、.jpg、.png 副檔名,但裡面其實是 PHP 程式碼。如果 Nginx / Apache 設定允許 .htaccess 把這些副檔名當 PHP 執行,那掃 PHP 就不夠了。

掃完 PHP 沒發現問題、感染跡象卻還在的話,就要往這個方向查。

貼給你的 AI 用

已經 SSH 進伺服器了?把下面這段貼給 ChatGPT 或 Claude,他會幫你判斷掃描結果:

我需要掃描 WordPress 網站有沒有被植入惡意程式碼。我已經 SSH 進伺服器了。

我的環境:
- 網站路徑:[填入,例如 /home/runcloud/webapps/mysite]
- PHP 版本:[填入]

請給我一組完整的掃描指令(grep eval+base64、goto 混淆、可疑函數、根目錄非標準 PHP、最近修改的 PHP),我貼回結果給你判斷哪些是惡意的、哪些是正常的。每個命中的檔案幫我分析要不要刪。

SSH 操作注意事項

SSH 指令送出去就是送出去了,沒有 Ctrl+Z。操作前請注意:

  • AI 給的指令,跑之前自己看一遍,確認路徑和檔名是對的再按 Enter。
  • 不要整段複製貼上一口氣跑完。一次一個指令,看到結果再下一步。
  • 刪除和覆蓋操作不可逆。備份沒做完之前,不要動任何清除步驟。
  • 不確定的時候就停下來問。問 AI、問主機商、問會的朋友,都比直接跑好。

SSH 基礎教學請看這篇。

搞不定?讓專人處理

WP 中毒救援 $5,500 起 | 外掛衝突排查含版面復原 $4,000 起

了解服務方案 →

文章分享