🕵️♀️ 全球140萬個網站遭殃!教你3分鐘揪出偽裝間諜
你有沒有想過,你家網站可能早就「被裝了竊聽器」,而你完全不知情?就在2026年7月,資安圈爆出一起超大規模的入侵事件——駭客利用一款叫做WP-ShellStorm的後門工具,一口氣鎖定超過140萬個網站,而且更狗血的是,這整起事件之所以曝光,居然是因為駭客自己「忘記鎖車門」被抓包!
今天這篇文章,我要用最生活化的方式,帶你搞懂這整起事件的來龍去脈,最後還會附上一份「傻瓜級」的自我檢查步驟,讓你也能在自己的伺服器上抓抓看有沒有可疑的「臥底」。
🎬 第一幕:小偷把作案工具忘在自家沒鎖的車庫
這起事件最有趣的地方,不是駭客有多厲害,而是他們有多「迷糊」。
想像一下:一個竊盜集團辛辛苦苦準備了整套開鎖工具、贓物清單、還有下一批要下手的目標名單,結果收工回家之後,居然忘記把車庫鐵門鎖上,就這樣大剌剌地曝光了整整22天。
這就是威脅情報公司 SOCRadar 發現這起事件的經過——駭客架設了一台伺服器,用來存放他們的攻擊工具跟紀錄,卻完全忘記設密碼保護。研究人員只是路過看了一眼,就撿到了整個犯罪組織的作案SOP,包含:
- ✅ 完整的攻擊工具(後門程式、漏洞掃描器)
- ✅ 詳細的操作紀錄(bash history)
- ✅ 一份長達140萬筆的「潛在肉雞」名單
💡 小提醒:這告訴我們一件事——就算是專業駭客,也會犯下「基本功沒做好」的低級錯誤。資安這件事,說穿了很多時候拚的不是誰的技術強,而是誰的「基本設定」做得確實。
🎯 第二幕:駭客到底是怎麼「進門」的?
很多人以為被駭客入侵,一定是自己「不小心點了什麼可疑連結」。但這次的手法完全不是這樣——駭客用的是「海放式打漏洞」戰術。
打個比方:這就像有個小偷不是專程來你家,而是拿著一把萬能鑰匙,走遍整條街,挨家挨戶去試每一戶的門鎖。只要哪一戶的鎖沒換新(也就是外掛程式沒更新),鑰匙一插就開,完全不需要你開門讓他進來。
這次駭客總共動用了27個已知漏洞,鎖定的都是WordPress常見外掛,戰績如下表:
| 被攻擊的外掛 | 白話解釋 | 戰果 |
|---|---|---|
| Breeze Cache Cleaner(快取外掛) | 幫網站加速的常見工具 | 4.5萬個目標中,1.7萬個被成功入侵 |
| ThemeREX Addons(佈景主題外掛) | 美化網站外觀用的工具 | 4.66萬個目標中,3,378個中招 |
| Joomla JCE(編輯器外掛) | 另一套建站系統的編輯工具 | 丟了56萬個目標,只成功77個(証明「有更新習慣」真的有用!) |
看到最後一列了嗎?Joomla JCE雖然被丟了最多次攻擊,成功率卻最低,因為多數用戶都已經修補了這個漏洞。這就是這次事件給我們最重要的啟示:你的外掛版本,就是你家門鎖的等級。
🥷 第三幕:後門怎麼躲貓貓躲到讓專家都找半天?
如果你以為後門程式就是一個大剌剌寫著「我是病毒」的檔案,那你就太小看這群駭客了。這次發現的主要後門down.php,做了四層偽裝,簡直像是套了四層洋蔥皮:
- 第一層:文字編碼混淆(讓人類肉眼看不懂)
- 第二層:壓縮加密(讓檔案看起來像亂碼)
- 第三層:變數名稱偽裝(連工程師掃過去都容易忽略)
- 第四層:最後才解開變成真正的「萬能鑰匙」
更狠的是,這個後門會偽裝成一般的「404錯誤頁面」給正常訪客看,也就是說,就算你自己點進網站檢查,看起來一切正常,其實裡面早就有人在裡面翻箱倒櫃。
最厲害(也最陰險)的一招,是遠端遙控用的程式會把自己改名偽裝成電腦系統內建的正常程序,具體來說就是偽裝成一種叫「kworker」的系統內部工作,讓人在檢查電腦「目前在跑什麼東西」的時候,誤以為它只是電腦自己在做家事,完全不會多想。
💡 生活化比喻:這就像小偷混進你家不是穿黑衣蒙面,而是換上一套跟你家管家一模一樣的制服,你看到他走來走去也不會覺得奇怪——因為他「看起來」就是自己人。
🔍 第四幕:3分鐘傻瓜自我檢測,看看你家有沒有「臥底」
看到這裡,你可能會緊張:那我自己的網站主機,要怎麼知道有沒有中招?別擔心,這邊教你一招最簡單的初步檢查,用電腦的「終端機」就能做,完全不用懂程式:
第一步:打開終端機,輸入以下指令:
|
1 |
ps aux | grep kworker |
第二步:看輸出結果的「格式」
| 狀態 | 長什麼樣子 | 白話解釋 |
|---|---|---|
| ✅ 正常 | [kworker/0:2-mm_percpu_wq] |
後面有清楚的「工作說明」尾巴,像正常員工都有名牌 |
| 🚨 異常 | [kworker/0:2] |
光禿禿沒有任何說明,像是沒戴名牌卻穿著制服到處走的可疑人物 |
如果你發現有「光禿禿沒有尾巴」的可疑項目,別自己亂刪,先截圖記錄,再找懂技術的朋友或資安人員協助確認。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
cat > /tmp/check-backdoor-full.sh << 'EOF' #!/bin/bash # ============================================ # 系統後門/持久化機制 全面快速檢測腳本 # 涵蓋範圍: # 1. 偽裝成 kworker 的可疑核心程序 # 2. Crontab 排程是否被植入可疑任務 # 3. SSH authorized_keys 是否被塞入陌生公鑰 # 4. systemd 服務是否有可疑的自啟動項目 # 5. 近期被修改過的系統關鍵檔案 # ============================================ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' TOTAL_ISSUES=0 echo "════════════════════════════════════════" echo "🔍 第一部分:kworker 偽裝程序檢測" echo "════════════════════════════════════════" KTHREADD_PID=$(pgrep -x kthreadd | head -1) SUSPICIOUS_COUNT=0 if [ -z "$KTHREADD_PID" ]; then echo -e "${YELLOW}⚠️ 找不到 kthreadd,建議人工檢查${NC}" else for pid in $(pgrep -f 'kworker'); do PNAME=$(ps -p "$pid" -o comm= 2>/dev/null) PPID=$(ps -p "$pid" -o ppid= 2>/dev/null | tr -d ' ') FLAG=0 REASONS="" if ! echo "$PNAME" | grep -qE '^kworker/[u]?[0-9]+:[0-9]+H?(-[a-zA-Z0-9_/-]+)?$'; then FLAG=1 REASONS="${REASONS}命名格式異常; " fi if [ "$PPID" != "$KTHREADD_PID" ] && [ "$PPID" != "2" ]; then FLAG=1 REASONS="${REASONS}父行程非kthreadd(PPID=$PPID); " fi if [ -e "/proc/$pid/exe" ]; then EXE_TARGET=$(ls -l "/proc/$pid/exe" 2>/dev/null | awk '{print $NF}') if [ -n "$EXE_TARGET" ]; then FLAG=1 REASONS="${REASONS}存在/proc/exe連結:$EXE_TARGET; " fi fi if [ "$FLAG" -eq 1 ]; then SUSPICIOUS_COUNT=$((SUSPICIOUS_COUNT+1)) echo -e "${RED}🚨 PID=$pid 名稱=$PNAME 原因:$REASONS${NC}" fi done if [ "$SUSPICIOUS_COUNT" -eq 0 ]; then echo -e "${GREEN}✅ 未發現偽裝的 kworker 程序${NC}" else TOTAL_ISSUES=$((TOTAL_ISSUES+SUSPICIOUS_COUNT)) fi fi echo "" echo "════════════════════════════════════════" echo "🔍 第二部分:Crontab 可疑排程檢測" echo "════════════════════════════════════════" CRON_HITS=0 # 檢查所有使用者的crontab + 系統層級排程 { for user in $(cut -f1 -d: /etc/passwd); do crontab -l -u "$user" 2>/dev/null | grep -v '^#' | grep -v '^$' | sed "s/^/[user:$user] /" done find /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly /etc/cron.monthly -type f 2>/dev/null -exec echo "[system] {}" \; -exec cat {} \; } > /tmp/.cron_dump_$$ # 揪出常見惡意特徵:curl/wget下載後直接執行、base64解碼執行、反彈shell、寫入陌生路徑 while IFS= read -r line; do if echo "$line" | grep -qE '(curl|wget).*\|.*(bash|sh)|base64 -d|/dev/tcp/|nc -e|mkfifo|chmod \+x /tmp|chmod \+x /var/tmp'; then CRON_HITS=$((CRON_HITS+1)) echo -e "${RED}🚨 可疑排程:$line${NC}" fi done < /tmp/.cron_dump_$$ rm -f /tmp/.cron_dump_$$ if [ "$CRON_HITS" -eq 0 ]; then echo -e "${GREEN}✅ 未發現明顯異常的排程任務${NC}" echo " (建議仍手動看一眼 crontab -l 確認每一條都是你熟悉的)" else TOTAL_ISSUES=$((TOTAL_ISSUES+CRON_HITS)) fi echo "" echo "════════════════════════════════════════" echo "🔍 第三部分:SSH authorized_keys 檢測" echo "════════════════════════════════════════" KEY_HITS=0 for keyfile in $(find /root /home -maxdepth 3 -name authorized_keys 2>/dev/null); do COUNT=$(grep -cve '^\s*$' "$keyfile" 2>/dev/null) echo "📄 $keyfile (共 $COUNT 把公鑰)" grep -v '^\s*$' "$keyfile" 2>/dev/null | while IFS= read -r key; do COMMENT=$(echo "$key" | awk '{print $NF}') echo " → 註記:$COMMENT" done done echo -e "${YELLOW}⚠️ 上面列出的每把公鑰請自行確認是不是你或團隊成員添加的,腳本無法自動判斷「陌生」與否${NC}" echo "" echo "════════════════════════════════════════" echo "🔍 第四部分:systemd 可疑自啟動服務" echo "════════════════════════════════════════" SYSTEMD_HITS=0 for svc in $(systemctl list-unit-files --type=service --state=enabled 2>/dev/null | awk '{print $1}' | grep '\.service$'); do SVC_PATH=$(systemctl show -p FragmentPath "$svc" 2>/dev/null | cut -d= -f2) if [ -n "$SVC_PATH" ] && echo "$SVC_PATH" | grep -qE '^/(tmp|var/tmp|dev/shm)/'; then SYSTEMD_HITS=$((SYSTEMD_HITS+1)) echo -e "${RED}🚨 可疑服務:$svc 定義檔位於臨時目錄:$SVC_PATH${NC}" fi done if [ "$SYSTEMD_HITS" -eq 0 ]; then echo -e "${GREEN}✅ 未發現定義在 /tmp、/dev/shm 等臨時目錄的自啟動服務${NC}" else TOTAL_ISSUES=$((TOTAL_ISSUES+SYSTEMD_HITS)) fi echo "" echo "════════════════════════════════════════" echo "🔍 第五部分:近7天內被修改的關鍵系統檔案" echo "════════════════════════════════════════" RECENT_FILES=$(find /etc /usr/bin /usr/sbin /usr/local/bin -type f -mtime -7 2>/dev/null) if [ -n "$RECENT_FILES" ]; then echo -e "${YELLOW}⚠️ 以下檔案在近7天內被修改過,請確認是否為你自己的操作(例如系統更新):${NC}" echo "$RECENT_FILES" | head -30 FILE_COUNT=$(echo "$RECENT_FILES" | wc -l) if [ "$FILE_COUNT" -gt 30 ]; then echo " ...(共 $FILE_COUNT 個,僅顯示前30個,多半是正常系統更新造成)" fi else echo -e "${GREEN}✅ 未發現近期異常修改的關鍵系統檔案${NC}" fi echo "" echo "════════════════════════════════════════" echo "🏁 總結" echo "════════════════════════════════════════" if [ "$TOTAL_ISSUES" -eq 0 ]; then echo -e "${GREEN}✅ 五項檢測皆未發現明確的自動化可判斷異常${NC}" echo " 建議仍手動複查 authorized_keys 與近期修改檔案清單這兩項(腳本無法完全自動判斷)" else echo -e "${RED}🔴 共發現 $TOTAL_ISSUES 項自動判定的可疑項目,建議處置流程:${NC}" echo "1️⃣ 先保留現場,不要急著刪除或kill,截圖/記錄上面的可疑項目" echo "2️⃣ 中斷該程序或服務對外的網路連線:ss -antp | grep <pid>" echo "3️⃣ 移除可疑crontab項目、可疑SSH公鑰、可疑systemd服務" echo "4️⃣ 檢查該主機上跑的網站程式(如WordPress)是否有外掛版本過舊未更新" echo "5️⃣ 若無法排除是否還有其他殘留後門,建議整台重灌重建,並在重建後第一時間更新所有軟體版本" fi echo "════════════════════════════════════════" EOF chmod +x /tmp/check-backdoor-full.sh bash /tmp/check-backdoor-full.sh |
🧯 第五幕:與其事後抓賊,不如提前鎖好門
看完整起事件,你會發現一個很殘酷的真相:這些受害網站,多數都是「本來可以避免」的悲劇。只要做好以下幾件事,你就能把中招機率降到最低:
- 🔐 外掛、佈景主題定期更新——這是最重要也最基本的一件事,就像家裡的門鎖該換就要換
- 🔑 SSH登入只用金鑰、別用密碼——密碼再複雜都可能被暴力破解,金鑰安全性高上不只一個檔次
- 🚪 不用的服務、外掛,直接移除——多一個沒在用的東西,就多一個可能被打穿的破口
- 📅 定期做健康檢查——就像定期健檢一樣,抓早期病灶總比等到病入膏肓便宜又省心
💬 碎念:資安這件事真的很像存錢——大家都知道很重要,但總是要等到真的出事了才會認真做。與其等網站被駭客賣掉存取權限才後悔,不如現在就花五分鐘檢查一下,真的划算多了 😌
📌 延伸閱讀與資料來源
- 駭客利用後門程式WP-ShellStorm入侵WordPress網站並兜售存取權限(iThome) [5]
- How WP-SHELLSTORM Exposed 1.4M WordPress Sites(SOCRadar 原始技術報告) [6]
看完這篇文章別忘了現在就去檢查一下自己的外掛版本喔!👍💪


