三台我們沒開過的機器,正在全網敲別人的 .env
三顆磁碟快照的離線解剖:一組 Rust 工具用我們的網路和帳單,去全網 542 條路徑撿別人的雲端金鑰。被封的是我們的 IP,被告的是我們的專案。
- 這不是挖礦、也不是勒索,是一台撿鑰匙的機器:內建 542 條敏感路徑,專找 .env、.git、service-account.json、JS bundle 裡的金鑰與錢包助記詞。
- 拉取式(pull)殭屍網路:worker 不開任何對外服務,主動連回 C2 領目標、回傳撿到的憑證。所以「收進 3.2 TB、送出 284 GiB」。
- 確認沒有 MIG 或執行個體範本,直接刪 3 台 VM 就永久停止;撿到的憑證沒留在我們磁碟上,受害的是被掃的第三方。
收比送多 11 倍的那三台機器
三台我們沒開過的 VM,9 天裡對外送出 284 GiB,卻收進 3,186 GiB。收比送多 11 倍——一台被入侵的機器如果在挖礦,這個比例會反過來。
2026-09-03,攻擊者用一把外洩的 Owner 級服務帳戶金鑰,在我們的 GCP 專案裡開了 3 台 e2-standard-4,裝上兩支 Rust 寫的 worker,把它們變成一組分散式掃描節點。它們對全網網站逐一探測 542 條敏感路徑,專找 .env、.git/config、service-account.json 與前端打包檔裡夾帶的金鑰。我們付的是算力、磁碟與出口流量;真正的受害者是被它掃到的第三方網站,因為撿到的憑證邊撿邊串流回攻擊者手上,一個字都沒留在我們的磁碟上。9/12 Google 停權整個專案,三台強制關機,9/13 先建磁碟快照再做離線解剖。
所以這篇要講的一件事是:他要的不是你的資料,是你的頻寬、你的帳單和你的 IP 信譽。「我們又沒什麼好偷的」是用一般人的眼睛在看自己;在他眼中,你的價值不是業務內容,而是你能被換成什麼——一個空專案的開機權限、一把還沒過期的 token、一台有對外頻寬的機器。下面這張表是他的菜單,也是決定你該先防哪一項的順序,排序依據是變現速度與門檻,不是資產帳面價值。
| 你的資產 | 駭客怎麼變現 | 變現速度/門檻 | 對他的價值 |
|---|---|---|---|
| 雲端運算權限(開 VM) | 開機器挖礦、當掃描節點(本次)、當代理轉租、發垃圾信 | 幾分鐘,帳算你的 | 極高 · 即時 |
| AI API Token | 轉租算力給第三方、包裝成便宜 AI 服務轉賣 | 即時,有現成黑市 | 高 · 即時 |
| 加密貨幣錢包(助記詞/私鑰) | 直接把資產轉走,不可逆 | 即時,一次性 | 極高 · 即時 |
| 金流金鑰(Stripe sk_live) | 操作真實金流、退款詐欺、測卡 | 快,但易被風控 | 高 · 中風險 |
| 寄信憑證(SES/SMTP) | 冒用你的網域發釣魚信(信譽度高、進得了收件匣) | 快,可大量 | 中高 |
| 原始碼/Token(GitHub) | 再撈更多金鑰、供應鏈投毒、勒索 | 需加工 | 中 · 可加值 |
| 個資/資料庫 | 打包上暗網、勒索、二次詐騙名單 | 需買家,慢 | 中 · 看規模 |
| 網站流量/SEO | 掛暗鏈、導購、惡意廣告 | 慢,長期寄生 | 低 |
第一列就是這次被拿走的東西。本次攻擊者從頭到尾不在乎我們是賣什麼的公司。
被借去當節點的,是一個花費 $0 的空專案
這個專案沒有自己的 VM、沒有對外服務,只有一支訊息機器人和幾支排程在寫試算表。金鑰怎麼外洩的,見〈排程回報「找不到帳戶」,被停權的是整個專案〉。
攻擊者建的 3 台規格一致:e2-standard-4(4 vCPU、16 GB)、Ubuntu 24.04 官方映像、200 GB pd-balanced、預設 VPC、外部 IP、網路標記 crusader、不掛服務帳戶、enable-oslogin=FALSE。不掛服務帳戶是刻意的:VM 就算被查,也偷不到 GCP 內部權限,同時少留一堆稽核足跡。
專案端原本已有的防護只有 Cloud Audit Logs 的 Admin Activity(預設開、400 天)。VPC Flow Logs 沒開、出口沒有白名單、沒有主機層日誌集中、沒有帳單異常偵測——這三台機器在網路層與主機層等於無人看管。
工具內建 542 條敏感路徑,對每個目標網站逐一探測。這份清單反過來讀,就是一張「什麼檔案不能公開放上網」的檢查表:
| 類別 | 例子 |
|---|---|
| 雲端金鑰 | .aws/credentials、.config/gcloud/credentials.db、service-account.json、.kube/config |
| 環境變數檔 | .env、config.env、application.properties、appsettings.json |
| 版本控制外洩 | .git/config、.gitconfig;連 CI/CD:.github/workflows、.gitlab-ci.yml、Jenkinsfile |
| 框架洩密端點 | Spring /actuator/heapdump、/actuator/env、phpinfo.php、Symfony _profiler |
| IDE/部署設定 | .vscode/sftp.json、.idea/dataSources.xml、.idea/WebServers.xml |
| SSH/資料庫 | .ssh/id_rsa、database.php、database.yml、backup.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 字典這幾種格式。把路徑表翻譯成「他在撿哪些服務的鑰匙」,就是下面這張:前八列是工具明確鎖定的憑證格式,受害者是被掃的第三方;後三列是我們這邊,攻擊者在我們的 VM 上自己建了兩組憑證,而他撿走了誰的什麼,我們查不到。
| 服務 | 憑證類型 | 用途 | 存在形式 | 放在哪 | 權限範圍 | 狀態 |
|---|---|---|---|---|---|---|
| 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 | 明文字串,常直接被打包進前端 JS | JS bundle、sourcemap、.env | 依金鑰限制設定,多數專案沒設限 | 第三方受害 |
| GCP:Service Account | Google Service KEY JSON | 後端程式以服務帳戶身分呼叫 Google API | JSON 檔,內含 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 VM | VM 內 root | 9/12 專案停權,VM 已 TERMINATED;磁碟保留至鑑識完成後才刪 |
| 攻擊者的 S3 相容集散地(他自己的) | 物件儲存存取金鑰 | worker 把撿到的內容上傳到他的儲存桶 | systemd EnvironmentFile 裡的明文變數 | 我們 VM 的 /etc/systemd/system 相關設定檔 | 他自己的儲存桶 | 屬攻擊端 IOC,內容不公開 |
| 他從我們這三台撿走了誰的什麼 | 不明 | — | — | 邊撿邊串流回 C2,本地暫存隨即清空 | — | 我們只有 findings 計數,看不到內容;VPC Flow Logs 沒開,也不知道掃了哪些網站 |
只要上面任何一種檔案曾經放進公開網站根目錄、Git 歷史或前端打包,就必須當作「已外洩」處理並輪替。 這支工具每天在全網掃這些路徑上百萬次,你還沒被撿到,只是因為還沒輪到你。
從開機到停權,只有三天有人在鍵盤前
這一篇的時間線只涵蓋「機器被開起來之後」。金鑰怎麼外洩、8/28 到 9/3 之間發生了什麼,見〈排程回報「找不到帳戶」,被停權的是整個專案〉;逐分鐘的全紀錄見教學個案。
- 9/3 12:40攻擊者用外洩金鑰直打 REST API,同一秒在 3 個區域(us-central1、us-east4、us-east1)、5 個可用區送出 5 台 e2-standard-4,成功 3 台Cloud Audit Logs:instances.insert ×5,其中 2 台 ZONE_RESOURCE_POOL_EXHAUSTED。
- 9/3 → 9/5攻擊者從 C2 IP 以 root 密碼 SSH 登入幾次,放上兩支 Rust worker 與 trufflehog,設好 systemd 後再也沒登入磁碟鑑識:auth.log、sshd 設定片段 99-crusader-idle.conf、/root 下的執行檔時間戳。
- 9/3 → 9/5三台幾乎閒置,CPU 2–3%,符合開機腳本名稱 idle-vmCloud Monitoring:每 6 小時約 3 GiB 進出。
- 9/5 20:00掃描開始,流量暴增;三台 9 天合計探測約 1.17 億次路徑、抓取數百萬支 JSMonitoring 流量曲線+磁碟上的 worker 進度日誌。
- 9/11 20:00其中兩台停止活動,剩一台跑到最後Cloud Monitoring VM 指標。
- 9/12 20:27Google 偵測到濫用,停權整個專案,三台強制關機VM 狀態 TERMINATED;服務帳戶回 invalid_grant。
- 9/133 顆 200 GB 磁碟建快照保存,做離線解剖快照與 evidence.tgz+.sha256。
他只登入過三天,剩下九天全是機器自己在跑。這門生意的人力成本,就是那三天。
七個階段,第四格是空的
攻擊者從來沒有在這三台機器上提過權,因為外面那把金鑰已經是 Owner。
他只花了一次開機的力氣,剩下的都是我們在出錢。
磁碟上留下了什麼
3 顆磁碟的離線解剖,重點在兩支主程式加一支開源工具。全程用唯讀方式解析 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_paths:
fetch_config拉 C2 設定 ·probe_one探測單一路徑 ·run_trufflehog/parse_trufflehog_jsonl·extract_aws_pairs抽 AWS 金鑰對 ·find_bip39_mnemonics錢包助記詞 ·scan_ses_windowSES 憑證 ·push_github_token·Spool離線暫存 ·Pusher回傳 - worker_js:
discover_js/discover_html·enumerate_chunkswebpack chunk ·parse_sourcemap還原原始碼 ·federation_remotes·extract_secrets·candidate_map_urls找.map
把這些能力接起來,運作架構是一個拉取式(pull)模型:工單從外面進來,成果往外面送,我們的機器只是中間那一層。
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 …
▼
全網受害網站
圖上那條對外通道只有五個端點,全部是 worker 主動發起的:
| C2 端點 | 用途 |
|---|---|
GET /api/targets/next | 領取下一批要掃的目標網站 |
POST /api/findings | 回傳撿到的憑證 |
POST /api/progress | 回報進度(讓 C2 知道節點還活著) |
POST /api/targets/done | 確認一批完成、釋放租約 |
GET /api/git/token | 領取 GitHub token 做進一步操作 |
清除之前還有一題要先回答:刪掉機器會不會自動長回來?「刪了又長回來」是真實存在的技術,但這次攻擊者沒有用,兩種層次要誠實區分。
| 層次 | 機制 | 刪 VM 後果 | 本次 |
|---|---|---|---|
| 開機層持久化 | systemd WantedBy=multi-user.target | 重開機照跑,但刪掉 VM 就沒了 | ✔ 有用(僅此層) |
| 基礎設施層自我複製 | 受管執行個體群組(MIG)+ 執行個體範本:設定「維持 N 台」,刪一台幾分鐘內自動長回來 | 刪 VM 沒用,要先刪 MIG 和範本 | ✗ 未使用(已確認) |
能證明的部分最後收成一張可以直接餵進 SIEM 的表。這是這篇對你最有立即用途的東西:
| 類型 | 指標 | 說明 |
|---|---|---|
| C2 | 93.123.109.230:8844 | 派工主機(AS48090)。同一 IP 也是盜用金鑰呼叫 GCP API 的來源 |
| 集散地 | 93.123.109.247:9000 | S3 相容儲存,bucket 名稱以 crusader-recon- 開頭 |
| 網段 | 93.123.109.0/24 | 建議整段出口封鎖 |
| 雜湊 | 6a41216ce80cd7e8… · 40b580d3e5183186… | worker_paths · worker_js(SHA-256 前 16) |
| 檔案 | /root/worker_paths · /root/worker_js · /root/worker.env · /root/spool/ · /usr/local/bin/trufflehog · /tmp/crusader.stopped | trufflehog 為開源工具,被兩支 worker 呼叫 |
| 服務 | crusader-paths-worker.service · crusader-js-worker.service | ExecStart 指向 /root、Restart=always |
| SSH | /etc/ssh/sshd_config.d/99-crusader-idle.conf | 開機腳本植入,開 root 密碼登入 |
| 雲端 | VM 名稱 crusader-gcp-probe-* · 防火牆 crusader-allow-ssh · 網路標記 crusader | e2-standard-4、無服務帳戶、多區同秒建立 |
| User-Agent | Mozilla/5.0 (X11; Linux x86_64) … Chrome/124.0 | worker 對外掃描時偽裝的瀏覽器 UA |
根因跟金鑰那一篇同一條,只是多長了三層
表面上的原因是三台我們沒開過的機器,9 天對外探測約 1.17 億次路徑。技術上,一把 Owner 級服務帳戶金鑰可以直接打 Compute Engine REST API 開機,而專案沒有地區限制、沒有 CPU 配額上限;機器開起來之後,主機層沒有日誌集中、出口沒有白名單、VPC Flow Logs 沒開,所以沒有任何一層看得見它。這兩層都有稽核記錄與帳單可以證明。
再往上是管理:沒有人為「這個專案不該有 VM」設下界線,也沒有人看帳單,三台機器整整 9 天不在任何儀表板上。
最後一層只能算推論,卻是最貴的一層——資產的價值一直用「我們賣什麼」來評估,而不是用「它能被換成什麼」。在這個口徑下,一個花費 $0 的空專案被歸類成不重要,於是它連最便宜的預算警示都沒有。同一條根因鏈,在金鑰那一篇停在控制平面,在這一篇往下掉到了主機層。
這種節點的設計目的,就是待在你的盲區
它成功了 9 天,而每一條被它繞過的訊號,都是我們自己相信的直覺。
第一個直覺是「有沒有開奇怪的 port」。三台 VM 不開任何監聽埠,拉取式 worker 完全繞過這個判斷法,掃 port 與入站防火牆都抓不到。第二個是流量:出口每 6 小時超過 100 GiB,但 VPC Flow Logs 沒開、出口也沒有白名單,流量再大也沒有任何一條規則會因此亮起來。
主機層同樣安靜。/root 下出現新的可執行檔、systemd 多了兩個非套件管理的服務,這些在有日誌集中與檔案完整性監控的環境裡是很吵的訊號,但這三台機器從來不在資產清單上,沒有基準線可以比。CPU 從 2–3% 跳到 10–30% 並持續 6 天也一樣——監控只監控你知道存在的機器。
最後是帳單:平常 $0 的專案每天多出 $12~21,而帳單帳戶沒有預算警示,一個「沒有業務」的專案也沒有人固定去開報表。五條訊號,四條免費,差別只在有沒有人設。
停權之後:先快照,再解剖
偵測那一格仍然不是我們的功勞。9/12 20:27 Google 停權專案,排程回報服務帳戶 invalid_grant,追查才發現專案裡有三台不認識的 VM,狀態是 TERMINATED。工具自己內建 kill-switch,但那是給操作者用的,不是我們按的。
圍堵幾乎沒得選:VM 已被強制關機、不再對外連線,我們能做的是撤銷金鑰與 Owner/Editor,斷掉攻擊者再開新機器的能力,細節見〈清單全部打勾的第 13 天,整個專案被停權了〉。
9/13 才是這篇存在的原因:先對 3 顆 200 GB 磁碟建立快照保存證據,再做離線解剖——唯讀掛載、ELF 符號表解析、時間軸重建,全程沒有執行過任何一支樣本;同時確認 res_migs.txt 與 res_templates.txt 都是空的,代表沒有會自動長回來的機制。惡意樣本本機隔離保存,不進版控。9/14 到 9/15 申訴解封,業務排程改走無金鑰代理,IOC 整理成 indicators.csv 餵進偵測規則。磁碟在鑑識完成前保留,所以帳單那幾天還在跑。
做對的都在清除之前,做錯的都在事發之前
這次處置有幾個動作,決定了後面還有沒有東西可以查:停權當天沒有急著刪 VM,先對磁碟建快照——沒有這一步,就沒有這篇文章裡的任何一行;第一個檢查項是 MIG 與執行個體範本,先確認「刪了會不會長回來」再談清除順序;全程唯讀解剖,掛載快照、讀符號表,沒有執行任何樣本;撿到的憑證屬於第三方,我們沒有去驗證任何一把,也沒有留存。
該改的四件,每一件都發生在事發之前。VPC Flow Logs 沒開,所以「掃了誰」這個對第三方最重要的問題永遠回答不了;沒有主機層日誌集中,auth.log 與 journal 只活在那 3 顆磁碟上,磁碟一刪就什麼都沒了;出口沒有白名單,而一個沒有業務的專案,VM 本來就不該連得出去;IOC 是事後才整理成規則的——如果 9/3 就有 instances.insert 告警,這 9 天根本不會存在。
改的不是防掃描,是讓「開得起機器」變難
當天要做的有四件:鑑識完成後刪除 3 台 VM、3 顆磁碟與 crusader-allow-ssh 防火牆規則,並再確認一次沒有 MIG 與執行個體範本;把 93.123.109.0/24 整段加入出口封鎖,IOC 做成 indicators.csv 餵進 SIEM;不用 VM 的專案把 CPU 配額設 0 並停用 Compute Engine API;用 trufflehog 與 gitleaks 掃一次自己的 repo 與部署目錄,對照那 542 條路徑先撿自己一遍。
一個月內補的是看得見:開啟 VPC Flow Logs 並對出口流量設基準線告警(單機每 6 小時的量級就夠用,規則名我們取 egress-pullnode-a7q,之後翻告警一眼就對得上這篇);出口防火牆改成白名單;systemd 單元與 /root、/tmp 可執行檔納入檔案完整性監控,ExecStart 指向 /root 即告警;對 instances.insert、firewalls.insert 設即時通知,並訂閱 Security Command Center 的高風險發現。
這一季要改的是結構與習慣:組織政策鎖可用地區、禁止外部 IP、強制 OS Login,不發長期服務帳戶金鑰;主機層日誌集中,不要讓證據只活在那顆磁碟上;事件證據包建立標準流程——先快照、再解剖、雜湊存證、樣本隔離不進版控;最後把「資產價值」的評估口徑從「我們賣什麼」改成「它能被換成什麼」,空專案也要有預算警示。
這些投入值不值得,換算成錢最清楚。我們付的那一欄有帳單可查;他付的那一欄我們拿不到帳單,只能用公開牌價推估,所以標成推論。
| 項目 | 用量 | 單價 | 期間 | 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/12 | 93.76 | 3,000 | 帳單依 SKU 分組頁面;稽核記錄 instances.insert 確認機型與台數 |
| 我們付的磁碟:3 顆 200 GB 帳單實付。worker 本身很小,磁碟是開機映像帶來的 | 186.21 GiB·月(pd-balanced) | 約 US$0.10/GB·月 | 9/3 → 帳單截止 | 19.89 | 636 | 帳單依 SKU 分組頁面(Balanced PD Capacity 兩列相加) |
| 我們付的出口流量:回傳 findings 帳單實付。撿到的憑證很小,這些流量多半是回傳與轉送 | 約 230 GiB 送出(前 4 大流量 SKU) | US$0.08~0.12/GiB,依目的地 | 9/5 → 9/12 | 24.80 | 794 | 帳單依 SKU 分組頁面;Monitoring sent_bytes_count |
| 掃描抓回來的內容:流入 3,186 GiB 這一列是整篇的重點:他挑雲端當節點,就是因為吃進來的那一邊不用錢 | 3.2 TB 下載受害網站內容 | GCP 流入不計費 | 9/5 → 9/12 | 0.00 | 0 | Monitoring received_bytes_count;GCP 官方牌價:internet ingress 免費 |
| 證據保存:3 顆磁碟快照 估:實際依壓縮後容量計。證據要留多久,就付多久 | 600 GB 標準快照 | 約 US$0.05/GiB·月(牌價) | 保存期間每月 | 30.00 | 960 | GCP 快照公開牌價;實際金額要等帳單結算 |
| 鑑識人力:3 顆磁碟離線解剖 估:取中間值 NT$27,500 × 2。這一列比帳單貴 12 倍,這才是事件的真正成本 | 約 2 人日:快照掛載、ELF 符號表解析、時間軸重建 | 顧問日費 NT$20,000~35,000(估) | 一次性 | 1718.75 | 55,000 | 本案鑑識工作範圍;日費為假設值 |
| 他付的:C2 派工主機與集散地 估:以 US$50/月 × 9/30 計。這是他這一趟唯一真正掏錢的地方 | 1 台防彈主機同時跑派工 API 與 S3 相容儲存 | 防彈 VPS 約 US$18~150/月(公開牌價) | 9 天 | 15.00 | 480 | C2 位址與 AS 可證;租金為公開牌價推估,我們拿不到他的帳單 |
| 他撿到的:數萬筆疑似憑證 內容不在我們的磁碟上,我們只有計數 | 9 天探測約 1.17 億次路徑、抓取數百萬支 JS | — | 9 天 | — | — | worker 邊撿邊串流回 C2,本地暫存即清空;findings 內容無從得知 |
| 換算成錢的量級(示意) 估:只算 1 把、只算 1 天。這一列解釋為什麼 US$15 的 C2 值得投資 | 假設其中只有 1 把是具管理員權限的 AWS 金鑰,拿去開 1 台 GPU 機 24 小時 | US$32.77/小時(p4d.24xlarge,us-east-1 牌價) | 1 天 | 786.54 | 25,169 | AWS 官方牌價 2026-09;「他確實這樣用」沒有證據,這是變現上限的量級示意 |
| 合計(僅可證明列) | 138.45 | 4,430 | ||||
他花 US$15,我們付 US$138.45 的帳單加上兩人日的鑑識。這 US$138.45 只算三台 VM 直接產生的算力、磁碟與流量,不含〈排程回報「找不到帳戶」,被停權的是整個專案〉算進去的 AI 模型呼叫與其餘雜項 SKU,加起來才是那篇的 US$146.10。這門生意的槓桿不在技術,在成本結構:他的邊際成本趨近於零,所以他不需要挑目標,也不在乎你是賣什麼的。
帶得走的五件事
從他的角度看,這是一門乾淨的生意:用你的 IP 與帳單,去全網撿別人的鑰匙。撿到 AWS 金鑰就開機器挖礦、發垃圾信、再擴散;撿到 SES 憑證就冒用網域發釣魚信;撿到 Google API 金鑰就盜刷地圖與 AI。風險那一欄是空的,因為被封的是你的 IP,被告的是你的專案。而他的工具不開對外 port、不掛服務帳戶、UA 偽裝成 Chrome,每一項都在壓低被發現的機會;那支 2026-07-14 才編譯的執行檔也說明了一件事——這是一個持續維護的產品,不是腳本小子的作品。
- 01他不在乎你賣什麼,只在乎你能換成什麼。一個花費 $0 的空專案,在他眼裡是「有對外頻寬、沒人看帳單」的完美節點。
- 02不是所有入侵都會讓 CPU 燒到 100%。收比送多 11 倍、CPU 只有 10–30%,這是一台在幫別人下載的機器。
- 03拉取式節點不開任何監聽埠。用「有沒有開奇怪的 port」判斷主機安不安全,在這個案子裡會全數誤判。
- 04先確認有沒有受管執行個體群組與執行個體範本,再談清除。沒有確認這一步,刪機器只是打地鼠。
- 05攻守用的是同一把尺。他用 trufflehog 撿你的憑證,你可以用同一支工具先撿自己一遍。
要把這件事拿去教學員,有一條清楚的界線:教「攻擊長什麼樣、怎麼被發現、怎麼防」,不教「怎麼造一把能傷人的武器」。
| 不要提供/示範 | 為什麼 |
|---|---|
| 惡意執行檔本體、原始碼、可運作的 C2 協定規格 | 拿了就能直接跑,等於散布武器 |
| 完整可貼上就用的 startup-script、542 條路徑清單原檔 | 是現成的攻擊 payload |
| 攻擊者的 S3 憑證、C2 token 等活的密鑰 | 用了就是存取他人系統 |
| 對真實、未授權的網站跑掃描示範 | 就算是教學,掃別人也是攻擊行為 |
| 「金鑰 → 可存取哪些資源」的實際對應表 | 等於把還沒輪替的鑰匙圈交出去 |
可以教的東西其實更多:kill-chain 分階段、MITRE ATT&CK 對照、時間線、去識別化的日誌片段、行為特徵、IOC 清單、偵測查詢、「為什麼會成功 → 對應防禦」的成對拆解,以及到函式名為止的能力清單。要動手就用隔離靶場:獨立的丟棄式專案或本機 VM,掃描目標是你自己架的靶機;攻擊端用只回報「我在跑」的良性 beacon 取代真的掃密工具;真樣本只在斷網沙箱做靜態解剖;學員動手的部分是寫偵測規則、跑獵捕查詢、判讀稽核記錄、練習封鎖與輪替。一句話:學員離開教室應該更會防守,而不是多一把可用的刀。
同一條界線也適用於這篇的十個關鍵字——每一個都是拿來認人、不是拿來動手的。
- 01變現速度(time-to-cash)決定你該先防哪一項的唯一標準。開 VM 的權限幾分鐘就能換到錢,個資要找買家;防護預算應該照這個順序分配。
- 02拉取式(pull)殭屍網路worker 不開任何對外 port,所以掃 port、看防火牆都抓不到它。要抓它只能看出口流量與帳單。
- 03.env 與 service-account.json542 條路徑裡最值錢的兩種檔案。只要它們曾經在網站根目錄、Git 歷史或前端打包裡出現過,就當作已外洩。
- 04trufflehog / gitleaks攻擊者拿它來偵測撿到的憑證,你可以拿同一支工具先掃自己一遍。攻守用的是同一把尺。
- 05systemd WantedBy=multi-user.target本案唯一的持久化層。認得它,才知道「重開機照跑,但刪掉 VM 就沒了」。
- 06受管執行個體群組(MIG)與執行個體範本真正會「刪了又長回來」的機制。先確認攻擊者沒用它,才敢說刪 VM 就結束了。
- 07流入不計費(ingress free)雲端的計價邏輯直接決定攻擊者的選擇。掃描型工具吃的是下載頻寬,所以雲端 VM 是它最便宜的家。
- 08sourcemap 與 webpack chunk前端打包會把後端的秘密一起帶上網。worker_js 整支程式就是為了這件事寫的。
- 09BIP39 助記詞12/24 個英文單字,撿到就等於錢包直接轉走、不可逆。這是他清單裡變現最快的一項。
- 10IOC(indicator of compromise)C2 網段、systemd 服務名、檔案雜湊。把它們變成偵測規則,才是這篇對你真正的用途。
如果今天早上你在帳單上看到三台陌生 VM
前 60 分鐘的順序是固定的,而且第一件事不是刪機器。
前十五分鐘先問「刪了會不會長回來」:確認有沒有受管執行個體群組與執行個體範本,兩個都空才代表刪掉就結束;接著對每一顆磁碟建立快照,那是之後唯一能回答「它在做什麼」的來源;然後從雲端層看出口流量曲線與帳單依 SKU 分組,先把「量」記下來,金額每天都在變。
第二個十五分鐘斷源:撤銷能開機器的那個身分的所有金鑰,否則你刪一台他開三台;把已知 C2 網段加入出口封鎖,阻斷還活著的節點回報;刪除對 0.0.0.0/0 開放的防火牆規則與攻擊者建立的網路標記。
剩下的半小時才輪到磁碟:唯讀掛載快照,看 /etc/systemd/system 有沒有非套件管理的服務、/root 與 /tmp 有沒有新的可執行檔、sshd_config.d 有沒有多出片段;對可疑執行檔算 SHA-256、讀 ELF 符號表列能力清單,不要執行它;再從 auth.log 與時間戳重建「攻擊者登入過幾次、最後一次是什麼時候」。一小時之後的慢工是:開 VPC Flow Logs、出口改白名單、主機層日誌集中,這三件決定下一次你能不能回答「掃了誰」。
回到開頭那個比例:收進 3,186 GiB、送出 284 GiB。那 3.2 TB 裡有多少是別人的 .env,我們的磁碟上一個字都沒留下。被掃到的那些網站至今不知道自己被掃過,而唯一能告訴他們的那份 VPC Flow Logs,我們當時沒有開。
你自己這邊,下面六步全部唯讀,十五分鐘內做得完。
全部唯讀,不改任何設定;做完你會知道自己有沒有同樣的破口。
- 在你自己的網站上,試三條最值錢的路徑(只對自己的網域做)。
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 才算過關。 - 掃自己的 repo 與部署目錄有沒有夾帶憑證。
trufflehog filesystem --no-update /path/to/repo gitleaks detect --source /path/to/repo --no-git看到什麼代表什麼:有 finding 就代表攻擊者的同一支工具也會撿到;要看的是「哪個身分」被撿到,不是「哪個檔案」。 - 看主機上有沒有非套件管理裝上去的 systemd 服務。
systemctl list-unit-files --state=enabled --no-pager grep -rl 'ExecStart=/root\|ExecStart=/tmp' /etc/systemd/system/ 2>/dev/null看到什麼代表什麼:ExecStart 指向 /root 或 /tmp 的服務,正常維運不會有;出現一個就當事件處理。 - 看有沒有不該存在的執行檔在暫存與家目錄。
find /root /tmp /var/tmp -maxdepth 2 -type f -perm -u+x -mtime -60 -ls 2>/dev/null看到什麼代表什麼:最近 60 天內出現的可執行檔,如果不是你放的,就是別人放的。 - 看這台機器的出口流量像不像一個掃描節點。
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 的樣子。 - 看雲端帳單有沒有出現「平常不會有」的服務。
gcloud billing accounts list # 主控台:帳單 → 報表 → 依服務分組,時間拉到 60 天看到什麼代表什麼:平常 $0 的專案出現 Compute Engine 或 Vertex AI,就是本案 9/4 那天的畫面。
每篇新文章一封:三點摘要、關鍵字定義、今天能做的一件事。
延伸閱讀
列為「風險最高」的那把金鑰,我們決定晚點再撤
上一次鑑識就點名它,但它擁有一萬多個檔案、七個以上的線上服務靠它活著,所以排在「先搬消費者再停用」。一個月後,它在五個小時內替別人跑了 6,350 萬 input token,整個專案被 Google 停權。
教學版:四道防線只要做到一道,這 15 天就不會發生
同一起事件的教學版:15 天逐分鐘攤開,每一步標出為什麼會成功、哪一道控制擋得下來。不發金鑰、不給 Owner、關掉沒用的 API、預算警示,四道都沒有。
排程回報「找不到帳戶」,被停權的是整個專案
一支只負責把資料寫進試算表的小程式,用的帳號卻是整個雲端專案權限最大的角色。金鑰六年沒換、外流後被用了 15 天:帳單 US$146,但「資料有沒有被看過」我們永遠答不出來。