INC-2026-0827highCrusader 掃密殭屍網路解剖

你的 VM 沒在挖礦, 它在幫別人撿鑰匙

三顆磁碟快照的離線解剖:一組 Rust 寫的分散式工具,用我們的網路和帳單,去全網掃別人網站上外洩的雲端金鑰。全部以防禦為目的,不含任何能重建武器的步驟。

事件期間 2026-09-03 → 09-12·整理於 2026-09-17·13 分鐘·9 可證明1 推論2 缺口
殭屍網路惡意程式分析GCP威脅獵捕駭客經濟學
tl;dr
  1. 這不是挖礦、也不是勒索,是一台撿鑰匙的機器:內建 542 條敏感路徑,專找 .env、.git、service-account.json、JS bundle 裡的金鑰與錢包助記詞
  2. 拉取式(pull)殭屍網路:worker 不開任何對外服務,主動連回 C2 領目標、回傳撿到的憑證。所以「收進 3.2 TB、送出 284 GiB」。
  3. 確認沒有 MIG 或執行個體範本,直接刪 3 台 VM 就永久停止;撿到的憑證沒留在我們磁碟上,受害的是被掃的第三方。
◉ 攻擊者視角他選的是「雲端運算權限」:變現最快、風險最低、規模可無限複製。他不在乎你賣什麼,只在乎帳單算不算得到你頭上。
◎ 防守者視角防護的第一步,是讓你手上每一項資產「就算被撿走,也換不到錢、或換錢的門檻高到不值得」。
本篇目錄
C2worker-1worker-2worker-3收進 3.2 TB · 送出 284 GiB · 沒開任何 port

先定義:駭客眼中的資產與變現

所有防護投入都應該從這張表開始。你的東西「值不值得防、要防多緊」,取決於它在攻擊者眼中能換多少錢、多快換到。攻擊者是理性的生意人,他挑的永遠是變現最快、風險最低的資產。

| 你的資產 | 駭客怎麼變現 | 變現速度/門檻 | 對他的價值 | |---|---|---|---| | 雲端運算權限(開 VM) | 開機器挖礦、當掃描節點(本次)、當代理轉租、發垃圾信 | 幾分鐘,帳算你的 | 極高 · 即時 | | AI API Token | 轉租算力給第三方、包裝成便宜 AI 服務轉賣 | 即時,有現成黑市 | 高 · 即時 | | 加密貨幣錢包(助記詞/私鑰) | 直接把資產轉走,不可逆 | 即時,一次性 | 極高 · 即時 | | 金流金鑰(Stripe sk_live) | 操作真實金流、退款詐欺、測卡 | 快,但易被風控 | 高 · 中風險 | | 寄信憑證(SESSMTP) | 冒用你的網域發釣魚信(信譽度高、進得了收件匣) | 快,可大量 | 中高 | | 原始碼/Token(GitHub) | 再撈更多金鑰、供應鏈投毒、勒索 | 需加工 | 中 · 可加值 | | 個資/資料庫 | 打包上暗網、勒索、二次詐騙名單 | 需買家,慢 | 中 · 看規模 | | 網站流量/SEO | 掛暗鏈、導購、惡意廣告 | 慢,長期寄生 | 低 |

關鍵心態:用駭客的眼睛,不是一般人的眼睛

「我們又沒什麼好偷的」是最危險的錯覺,那是一般人的視角。在駭客眼中,你的價值不是你的業務內容,而是你能被換成什麼:一個空專案的開機權限、一把還沒過期的 token、一台有對外頻寬的機器。本次攻擊者根本不在乎我們是賣什麼的公司。

攻擊者鎖定的目標

工具內建 542 條敏感路徑,對每個目標網站逐一探測。這些路徑直接告訴我們「什麼檔案不能公開放上網」:

| 類別 | 例子 | |---|---| | 雲端金鑰 | .aws/credentials.config/gcloud/credentials.dbservice-account.json.kube/config | | 環境變數檔 | .envconfig.envapplication.propertiesappsettings.json | | 版本控制外洩 | .git/config.gitconfig;連 CI/CD:.github/workflows.gitlab-ci.ymlJenkinsfile | | 框架洩密端點 | Spring /actuator/heapdump/actuator/envphpinfo.php、Symfony _profiler | | IDE/部署設定 | .vscode/sftp.json.idea/dataSources.xml.idea/WebServers.xml | | SSH/資料庫 | .ssh/id_rsadatabase.phpdatabase.ymlbackup.sql.pgpass | | 前端打包夾帶 | JS bundle、sourcemap.map)、webpack chunk、module federation remote | | 加密貨幣錢包 | BIP39 助記詞(12/24 字),從掃到的內容裡比對字典還原 |

撿到內容後,用開源工具 trufflehog 加上自製比對,鎖定這些憑證格式:AKIA…ASIA…(AWS)、SES SMTP 憑證、AIza…(Google API)、ghp_…github_pat_…sk_live_…(Stripe)、BIP39 字典。

第一課:只要上面任何一種檔案曾經放進公開網站根目錄、Git 歷史或前端打包,就必須當作「已外洩」處理並輪替。這支工具每天在全網掃這些路徑上百萬次。你不被它撿到,只是因為還沒輪到你。

這次外洩了什麼

把上面那張路徑表翻譯成「他到底在撿哪些服務的鑰匙」。前八列是工具明確鎖定的憑證格式,受害者是被掃的第三方;後三列是我們這邊:攻擊者在我們的 VM 上自己建了兩組憑證,而他撿走了誰的什麼,我們查不到。

leaked credentials這支工具在撿的每一種鑰匙
服務憑證類型用途存在形式放在哪權限範圍狀態
AWS:IAM 使用者與臨時憑證access key(AKIA 開頭)、臨時憑證(ASIA 開頭)程式存取物件儲存、運算、寄信等全部 AWS 服務INI 格式設定檔的 profile 區段,或明文環境變數網站可讀的 .aws/credentials、.env、Git 歷史、前端打包檔依該 IAM 使用者的政策,最糟是 AdministratorAccess第三方受害,非我方憑證
AWS SES:寄信服務SMTP 使用者名稱與密碼用你的網域寄交易信明文環境變數或應用程式設定檔.env、application.properties、appsettings.json代表你的網域寄信,收件匣到達率高第三方受害
Google Cloud:API 金鑰API key(AIza 開頭)呼叫地圖、AI 等計費 API明文字串,常直接被打包進前端 JSJS bundle、sourcemap、.env依金鑰限制設定,多數專案沒設限第三方受害
GCP:Service AccountGoogle Service KEY JSON後端程式以服務帳戶身分呼叫 Google APIJSON 檔,內含 private_key 的 PEM 區塊service-account.json 放在網站可讀目錄或 repo 裡看綁的角色。最糟就是 Owner,也就是我們自己那把第三方受害(我方那把見另一篇防暴筆記)
GitHub個人存取權杖(ghp_ 或 github_pat_ 開頭)拉私有 repo、推 commit、觸發 CI明文字串.git/config、.env、CI 設定檔(工作流程 YAML)依 token scope,可到私有 repo 全寫入第三方受害;工具另有一支端點專門去領 GitHub token
Stripe:金流祕密金鑰(sk_live 開頭)建立付款、退款等真實金流操作明文字串.env、後端設定檔可操作真實金流,但容易被風控擋下
SSH私鑰(id_rsa)登入伺服器PEM 私鑰檔,無密碼保護時可直接使用.ssh/id_rsa 被放進網站可讀目錄或 commit 進 repo該私鑰授權的所有主機
加密貨幣錢包BIP39 助記詞(12 或 24 個英文單字)控制錢包資產純文字單字序列,藏在備份檔、筆記或原始碼註解裡掃到的任何文字內容,用字典比對還原等同錢包所有權,轉走不可逆
我們的 3 台 VM(攻擊者自建)root 密碼與密碼式 SSH 登入他自己登入把工具裝上去、設好常駐由開機腳本寫進 sshd 設定片段(99-crusader-idle.conf)3 台 worker VMVM 內 root9/12 專案停權、磁碟快照保存後刪除 VM
攻擊者的 S3 相容集散地(他自己的)物件儲存存取金鑰worker 把撿到的內容上傳到他的儲存桶systemd EnvironmentFile 裡的明文變數我們 VM 的 /etc/systemd/system 相關設定檔他自己的儲存桶屬攻擊端 IOC,內容不公開
他從我們這三台撿走了誰的什麼不明邊撿邊串流回 C2,本地暫存隨即清空我們只有 findings 計數,看不到內容;VPC Flow Logs 沒開,也不知道掃了哪些網站
憑證本身已遮蔽或失效;這裡只說明它是哪個服務、拿來做什麼、以什麼形式存放,讓你能對照自己的環境。

工具解剖:兩支 Rust 程式

磁碟上留下兩支主程式加一支開源工具。用唯讀方式解析 ELF 符號表(程式沒有 strip,函式名稱都在),只看「它有哪些能力」,不還原「它怎麼實作」。

| 檔案 | 語言/編譯 | 角色 | SHA-256(前 16) | |---|---|---|---| | /root/worker_paths | Rust 1.97(2026-07-14)Ubuntu 24.04 | 路徑探測器:對目標逐條試 542 個敏感路徑 | 6a41216ce80cd7e8 | | /root/worker_js | 同上 | 前端爬蟲:抓 JS/sourcemap/chunk 挖夾帶的密鑰 | 40b580d3e5183186 | | /usr/local/bin/trufflehog | Go(開源) | 憑證偵測引擎,被上面兩支呼叫 | — |

從符號表還原的能力清單(函式名層級):

  • worker_pathsfetch_config 拉 C2 設定 · probe_one 探測單一路徑 · run_trufflehog / parse_trufflehog_jsonl · extract_aws_pairs 抽 AWS 金鑰對 · find_bip39_mnemonics 錢包助記詞 · scan_ses_window SES 憑證 · push_github_token · Spool 離線暫存 · Pusher 回傳
  • worker_jsdiscover_js / discover_html · enumerate_chunks webpack chunk · parse_sourcemap 還原原始碼 · federation_remotes · extract_secrets · candidate_map_urls.map

運作架構:C2 拉取模型

        C2 派工主機                       攻擊者 S3 集散地
     93.123.109.230:8844                93.123.109.247:9000
     (防彈主機 AS48090)                 bucket crusader-recon-…
           │  ① GET /api/targets/next          ▲
           │  ③ POST /api/findings /progress   │ ④ 大量下載的內容從這裡進出
           ▼                                   │
   ┌──────────────────────────────────────────────┐
   │  我們專案的 3 台 worker VM                    │
   │  crusader-gcp-probe-…-1/2/5                   │
   │  worker_paths + worker_js · e2-standard-4     │
   │  無服務帳戶 · 不開任何對外 port               │
   └──────────────────────────────────────────────┘
           │  ② 掃描 .env / .git / JS bundle …
           ▼
        全網受害網站

拉取式(pull)殭屍網路:worker 不開任何對外服務,而是主動連回 C2 領工單。這就是為什麼 VM「收進 3.2 TB、只送出 284 GiB」:它在下載受害網站的內容來掃描,撿到的精華(憑證)很小,回傳量自然小。沒有 nginx、沒有 apache,全靠內建的 Rust HTTP 客戶端。

| C2 端點 | 用途 | |---|---| | GET /api/targets/next | 領取下一批要掃的目標網站 | | POST /api/findings | 回傳撿到的憑證 | | POST /api/progress | 回報進度(讓 C2 知道節點還活著) | | POST /api/targets/done | 確認一批完成、釋放租約 | | GET /api/git/token | 領取 GitHub token 做進一步操作 |

完整攻擊鏈

發生了什麼 · 9/3 12:40
沒有用 gcloud、沒有登入主控台,拿外洩金鑰簽 token 直接打 Compute Engine REST API(instances.insert)。同一秒 4 個地區送出 5 台,成功 3 台。每台請求裡就帶好開機腳本。
當時留下的訊號
稽核記錄:instances.insert、來源 IP 非公司、user-agent=gzip(gfe)、一批同時多區。
能擋下它的控制
不用 VM 的專案把 CPU 配額設 0;組織政策鎖地區;監控 instances.insert 即時告警。

持久化與「自我複製」的真相

「就算刪掉 VM 也會自動重建」是真實存在的技術,但這次攻擊者沒有用。誠實區分兩種層次:

| 層次 | 機制 | 刪 VM 後果 | 本次 | |---|---|---|---| | 開機層持久化 | systemd WantedBy=multi-user.target | 重開機照跑,但刪掉 VM 就沒了 | ✔ 有用(僅此層) | | 基礎設施層自我複製 | 受管執行個體群組(MIG)+ 執行個體範本:設定「維持 N 台」,刪一台幾分鐘內自動長回來 | 刪 VM 沒用,要先刪 MIG 和範本 | ✗ 未使用(已確認) |

給資安課程:怎麼安全地 step-by-step

想把「攻擊者的詳細路徑」拿去教學員,同時不傷害任何人、也不做出重現攻擊的細節。這兩件事可以並存,關鍵是分清楚「可以教的形狀」與「不能給的武器」。

| 不要提供/示範 | 為什麼 | |---|---| | 惡意執行檔本體、原始碼、可運作的 C2 協定規格 | 拿了就能直接跑,等於散布武器 | | 完整可貼上就用的 startup-script、542 條路徑清單原檔 | 是現成的攻擊 payload | | 攻擊者的 S3 憑證、C2 token 等活的密鑰 | 用了就是存取他人系統 | | 對真實、未授權的網站跑掃描示範 | 就算是教學,掃別人也是攻擊行為 | | 「金鑰 → 可存取哪些資源」的實際對應表 | 等於把還沒輪替的鑰匙圈交出去 |

可以教的:kill-chain 分階段、MITRE ATT&CK 對照、時間線、去識別化的日誌片段、行為特徵、IOC 清單、偵測查詢、「為什麼會成功 → 對應防禦」的成對拆解、能力清單(函式名層級)。

要動手,就用隔離靶場:獨立的丟棄式專案或本機 VM,掃描目標是你自己架的靶機;攻擊端用只回報「我在跑」的良性 beacon 取代真的掃密工具;真樣本只在斷網沙箱做靜態解剖;學員的動手部分是寫偵測規則、跑獵捕查詢、判讀稽核記錄、練習封鎖與輪替。

一句話原則

教「攻擊長什麼樣、怎麼被發現、怎麼防」,不教「怎麼造一把能傷人的武器」。學員離開教室應該更會防守,而不是多一把可用的刀。

他的商業模式:用你的 IP 與帳單,去全網撿別人的鑰匙。
  • 撿到 AWS 金鑰 → 開 EC2 挖礦、發垃圾信、再擴散。撿到 SES 憑證 → 冒用網域發釣魚信。撿到 Google API 金鑰 → 盜刷 Maps、Gemini。
  • 用你的 VM 掃,被封的是你的 IP,被告的是你的專案。他零風險。
  • VM 不開對外 port、不掛服務帳戶、UA 偽裝 Chrome,每一項都在降低被偵測的機會。
  • 他的工具 2026-07-14 才編譯,Rust 1.97、Ubuntu 24.04。這是一個持續維護的產品,不是腳本小子。

這門生意的帳

把整件事換算成錢,才看得懂他為什麼要做這門生意。我們付的那一欄有帳單可查;他付的那一欄我們拿不到帳單,只能用公開牌價推估,所以標成推論。

cost他花多少、我們付多少
項目用量單價期間US$NT$舉證
我們付的算力:3 台 e2-standard-4
帳單實付:Core 39.05+21.99,Ram 20.93+11.79
約 2,685 vCPU·小時(9 天)E2 Core+E2 Ram 分開計價9/3 → 9/1293.763,000帳單依 SKU 分組頁面;稽核記錄 instances.insert 確認機型與台數
我們付的磁碟:3 顆 200 GB
帳單實付。worker 本身很小,磁碟是開機映像帶來的
186.21 GiB·月(pd-balanced)約 US$0.10/GB·月9/3 → 帳單截止19.89636帳單依 SKU 分組頁面(Balanced PD Capacity 兩列相加)
我們付的出口流量:回傳 findings
帳單實付。撿到的憑證很小,這些流量多半是回傳與轉送
約 230 GiB 送出(前 4 大流量 SKU)US$0.08~0.12/GiB,依目的地9/5 → 9/1224.80794帳單依 SKU 分組頁面;Monitoring sent_bytes_count
掃描抓回來的內容:流入 3,186 GiB
這一列是整篇的重點:他挑雲端當節點,就是因為吃進來的那一邊不用錢
3.2 TB 下載受害網站內容GCP 流入不計費9/5 → 9/120.000Monitoring received_bytes_count;GCP 官方牌價:internet ingress 免費
證據保存:3 顆磁碟快照
估:實際依壓縮後容量計。證據要留多久,就付多久
600 GB 標準快照約 US$0.05/GiB·月(牌價)保存期間每月30.00960GCP 快照公開牌價;實際金額要等帳單結算
鑑識人力:3 顆磁碟離線解剖
估:取中間值 NT$27,500 × 2。這一列比帳單貴 12 倍,這才是事件的真正成本
約 2 人日:快照掛載、ELF 符號表解析、時間軸重建顧問日費 NT$20,000~35,000(估)一次性1718.7555,000本案鑑識工作範圍;日費為假設值
他付的:C2 派工主機與集散地
估:以 US$50/月 × 9/30 計。這是他這一趟唯一真正掏錢的地方
1 台防彈主機同時跑派工 API 與 S3 相容儲存防彈 VPS 約 US$18~150/月(公開牌價)9 天15.00480C2 位址與 AS 可證;租金為公開牌價推估,我們拿不到他的帳單
他撿到的:數萬筆疑似憑證
內容不在我們的磁碟上,我們只有計數
9 天探測約 1.17 億次路徑、抓取數百萬支 JS9 天worker 邊撿邊串流回 C2,本地暫存即清空;findings 內容無從得知
換算成錢的量級(示意)
估:只算 1 把、只算 1 天。這一列解釋為什麼 US$15 的 C2 值得投資
假設其中只有 1 把是具管理員權限的 AWS 金鑰,拿去開 1 台 GPU 機 24 小時US$32.77/小時(p4d.24xlarge,us-east-1 牌價)1 天786.5425,169AWS 官方牌價 2026-09;「他確實這樣用」沒有證據,這是變現上限的量級示意
合計(僅可證明列)138.454,430
匯率假設 1 USD ≈ NT$32。單價為公開牌價或帳單實付,來源:本案 GCP 帳單報表(依 SKU 分組)截圖 2026-09-15;Cloud Monitoring VM 網路指標;防彈主機與 AWS GPU 機型為公開牌價,查價 2026-09。「舉證」欄標明每筆損失的證據來源與等級( 可證明 推論 缺口)。

他花 US$15,我們付 US$138.45 的帳單加上兩人日的鑑識。這門生意的槓桿不在技術,在成本結構:他的邊際成本趨近於零,所以他不需要挑目標,也不在乎你是賣什麼的。

重點學習

keywords重點學習:最需要學習的 10 個關鍵字10
  1. 01
    變現速度(time-to-cash)
    決定你該先防哪一項的唯一標準。開 VM 的權限幾分鐘就能換到錢,個資要找買家;防護預算應該照這個順序分配。
  2. 02
    拉取式(pull)殭屍網路
    worker 不開任何對外 port,所以掃 port、看防火牆都抓不到它。要抓它只能看出口流量與帳單。
  3. 03
    .env 與 service-account.json
    542 條路徑裡最值錢的兩種檔案。只要它們曾經在網站根目錄、Git 歷史或前端打包裡出現過,就當作已外洩。
  4. 04
    trufflehog / gitleaks
    攻擊者拿它來偵測撿到的憑證,你可以拿同一支工具先掃自己一遍。攻守用的是同一把尺。
  5. 05
    systemd WantedBy=multi-user.target
    本案唯一的持久化層。認得它,才知道「重開機照跑,但刪掉 VM 就沒了」。
  6. 06
    受管執行個體群組(MIG)與執行個體範本
    真正會「刪了又長回來」的機制。先確認攻擊者沒用它,才敢說刪 VM 就結束了。
  7. 07
    流入不計費(ingress free)
    雲端的計價邏輯直接決定攻擊者的選擇。掃描型工具吃的是下載頻寬,所以雲端 VM 是它最便宜的家。
  8. 08
    sourcemap 與 webpack chunk
    前端打包會把後端的秘密一起帶上網。worker_js 整支程式就是為了這件事寫的。
  9. 09
    BIP39 助記詞
    12/24 個英文單字,撿到就等於錢包直接轉走、不可逆。這是他清單裡變現最快的一項。
  10. 10
    IOC(indicator of compromise)
    C2 網段、systemd 服務名、檔案雜湊。把它們變成偵測規則,才是這篇對你真正的用途。

今天就可以來試試

try today今天就可以來試試15 分鐘

全部唯讀,不改任何設定;做完你會知道自己有沒有同樣的破口。

  1. 在你自己的網站上,試三條最值錢的路徑(只對自己的網域做)。
    for p in .env .git/config .aws/credentials; do
      curl -s -o /dev/null -w "%{http_code} $p\n" https://YOUR-DOMAIN/$p
    done
    看到什麼代表什麼:任何一條回 200 就是已外洩,該檔案裡的每一把金鑰今天都要輪替;回 403/404 才算過關。
  2. 掃自己的 repo 與部署目錄有沒有夾帶憑證。
    trufflehog filesystem --no-update /path/to/repo
    gitleaks detect --source /path/to/repo --no-git
    看到什麼代表什麼:有 finding 就代表攻擊者的同一支工具也會撿到;要看的是「哪個身分」被撿到,不是「哪個檔案」。
  3. 看主機上有沒有非套件管理裝上去的 systemd 服務。
    systemctl list-unit-files --state=enabled --no-pager
    grep -rl 'ExecStart=/root\|ExecStart=/tmp' /etc/systemd/system/ 2>/dev/null
    看到什麼代表什麼:ExecStart 指向 /root 或 /tmp 的服務,正常維運不會有;出現一個就當事件處理。
  4. 看有沒有不該存在的執行檔在暫存與家目錄。
    find /root /tmp /var/tmp -maxdepth 2 -type f -perm -u+x -mtime -60 -ls 2>/dev/null
    看到什麼代表什麼:最近 60 天內出現的可執行檔,如果不是你放的,就是別人放的。
  5. 看這台機器的出口流量像不像一個掃描節點。
    ss -tn state established | awk 'NR>1 {print $4}' | wc -l
    ss -tn state established | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
    看到什麼代表什麼:同時數百條到上千個不同目的地的短連線,而你的服務沒有理由去連外面,這就是 worker 的樣子。
  6. 看雲端帳單有沒有出現「平常不會有」的服務。
    gcloud billing accounts list
    # 主控台:帳單 → 報表 → 依服務分組,時間拉到 60 天
    看到什麼代表什麼:平常 $0 的專案出現 Compute Engine 或 Vertex AI,就是本案 9/4 那天的畫面。
newsletter
下一篇拆解直接寄到信箱

每篇新文章一封:三點摘要、攻擊者/防守者視角、今天能做的一件事。或先 加入會員 記錄你完成的任務。