教學個案:一把 Google Service KEY JSON, 從外洩到停權的 15 天全紀錄
一支 LINE Bot 用來讀寫試算表的 GCP:Service Account,金鑰放了六年沒換,而且帳戶本身是專案 Owner。金鑰外洩後,攻擊者先盜用 AI 模型,再開 VM 轉手給別人大量下載,直到 Google 偵測到濫用、停權整個專案,我們才發現。這篇是內部教學版:每一步都標出為什麼能成功、哪一道控制擋得下來,最後附鑑識指令與討論題。
- 外洩的是一把 2020 年建立的 Google Service KEY JSON,被 commit 進至少兩個 repo,也放進部署平台的環境變數。平台 8/27 出事,36 小時內金鑰就被用。
- 攻擊者第一個動作不是開 VM,是測 Vertex AI 上哪些模型能用;9/3 才開防火牆與 3 台 e2-standard-4,前 2.5 天閒置,之後被拿去大量下載,收進 3.2 TB。
- 帳單 US$146.10 全部可歸因,稽核記錄 14 筆完整;但 VM 裡做了什麼、資料有沒有被讀、流量去哪,因為三種 log 都沒開,永遠答不出來。
本篇目錄
數字先講
時間一律為台灣時間(UTC+8)。整理於 2026-09-15,這篇教學版於 2026-09-17 去識別化後發布。
這次外洩了什麼
| 服務 | 憑證類型 | 用途 | 存在形式 | 放在哪 | 權限範圍 | 狀態 |
|---|---|---|---|---|---|---|
| GCP IAM 服務帳戶(GCP:Service Account) | 使用者管理金鑰:Google Service KEY JSON | LINE Bot 讀寫 Google 試算表、上傳陳列照片到 Drive 的排程 | JSON 檔(含 private_key 的 PEM 私鑰、client_email、private_key_id);在部署平台則是整段 JSON 塞進一個環境變數,或 base64 後再塞 | 至少兩個 repo 的同一個目錄(commit 進 git 歷史)+部署平台服務的環境變數 | roles/owner(整個專案) | 2026-09-13 刪除金鑰、拿掉 Owner;金鑰 2020-09 建立,6 年未輪替 |
| AWS IAM 使用者 | access key(AKIA… + secret) | 應用程式存取 S3/SES 等 AWS 服務 | 明文環境變數(AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) | 部署平台服務的環境變數 | 依各 IAM policy | 2026-08-29~30 已輪替(平台清單內) |
| MySQL/PostgreSQL 資料庫 | 帳號密碼 | 各服務連線資料庫 | 明文環境變數或連線字串(DATABASE_URL) | 部署平台服務的環境變數 | 該資料庫全部資料 | 2026-08-29~30 已輪替(平台清單內) |
| 其他符合憑證格式的環境變數 | 不明(平台通知只說「符合憑證格式」) | 不明 | 明文環境變數 | 部署平台 | 不明 | 未逐一確認;平台未提供清單 |
第一列是這篇的主角:同一把 KEY JSON 存在三個地方(兩個 repo 的 git 歷史、部署平台的環境變數),8/29 的輪替只照平台的環境變數清單做,前兩個地方沒人想到。憑證清冊要以「身分」為單位,不是以「存放位置」為單位。
攻擊路徑
外洩的 Google Service KEY JSON(repo 內 commit、部署平台環境變數)→ 攻擊者主機(93.123.109.230,AS48090 主機商,自動化工具)→ 用私鑰換 token,以 GCP:Service Account 的身分行動 → 因為它是 roles/owner,三條路同時打開:
| 路 | 起點 | 做了什麼 | 結果 | |---|---|---|---| | Vertex AI | 8/28 起 | 試呼叫 Claude 27 次(404/429)→ 接受 Model Garden 使用條款 → Gemini 成功 212 次 | US$2.79 | | Compute Engine | 9/3 起 | 防火牆對全網開 22、3000–9999 → 5 台 VM 同時開,3 台成功 → 開機腳本開啟 root 密碼 SSH → 收進 3.2 TB、送出 284 GiB | US$143.32 | | Sheets/Drive | 不明 | 可讀所有分享給這個帳戶的檔案 | 沒開資料存取記錄,無法排除被讀 |
關鍵在中間那一格:服務帳戶有 Owner 權限,所以一把原本只用來寫試算表的金鑰,能打開整個專案的所有服務。第三列是「有能力但沒有記錄可以確認」。
通知後金鑰仍有效:17 天
- 8/27部署平台通知環境變數外洩;我方依平台清單輪替 AWS 金鑰與資料庫密碼平台通知信與輪替紀錄。
- 8/27(推定)Google Service KEY JSON 隨環境變數被取走無直接證據,只有時間相關性。
- 8/28 23:00攻擊者首次使用金鑰(Vertex AI RawPredict)Cloud Audit Logs:callerIp 93.123.109.230。
- 8/29 03:21攻擊者替專案接受 Model Garden 使用條款Audit Logs:AcceptPublisherModelEula。
- 9/3 12:38–12:40開防火牆、同一秒送出 5 台 VM,3 台成功Audit Logs:firewalls.insert、instances.insert ×5(2 台 ZONE_RESOURCE_POOL_EXHAUSTED)。
- 9/5 20:00VM 開始被大量使用,一直到 9/11Cloud Monitoring:每 6 小時流入從 3 GiB 暴增到 100 GiB 以上。
- 9/7 → 9/12Gemini GenerateContent 成功 212 次Monitoring api/request_count 依 credential_id。
- 9/12 20:27Google 停權整個專案服務帳戶回 invalid_grant;VM 狀態 TERMINATED。
- 9/13刪除專案內 7 把使用者金鑰、拿掉 5 個服務帳戶的 Owner/EditorAudit Logs:DeleteServiceAccountKey、SetIamPolicy。
- 9/14 → 9/15送出申訴,隔日解封申訴單與解封通知。
8/29~8/30 的輪替只處理了環境變數清單上的 AWS 金鑰和資料庫密碼。以 Google Service KEY JSON 形式散落在 repo 裡的 GCP 服務帳戶金鑰,一直到 9/13 才被處理。從通知到金鑰失效,17 天。
逐步拆解
每一步標出 MITRE ATT&CK 技術編號、當時留下的證據、為什麼能成功,以及哪一個控制可以擋下來。
1. 取得金鑰(8/27 推定 · T1552.001)
這把金鑰 2020 年建立,之後以 Google Service KEY JSON 的形式被 commit 進至少兩個 repo 的同一個目錄,也可能被放進部署平台服務的環境變數。8/27 平台發生事件,攻擊者取走了符合憑證格式的環境變數。
第一次盜用發生在隔天晚上。這把金鑰在 repo 裡放了好幾年都沒被濫用,卻在平台出事後 36 小時內開始被使用,所以研判來源是平台外洩,但沒有直接證據。
為什麼能成功:長期有效的私鑰檔案被複製到多個地方,沒有人知道全部位置在哪。 可以怎麼擋:不發長期金鑰。改用 Workload Identity 或不需私鑰的代理服務;非發不可就設組織政策讓金鑰自動過期。
2. 用金鑰登入,測試能用哪些 AI 模型(8/28 23:00 · T1078.004)
攻擊者用私鑰簽 JWT 換成 access token,直接以 GCP:Service Account 的身分呼叫 API。第一件事不是開 VM,而是在 us-central1、us-east5、europe-west1/4 呼叫 Vertex AI 上的 Claude 模型(RawPredict),全部回 404 或 429。8/29 03:21 接著呼叫 AcceptPublisherModelEula,替我們的專案接受了模型使用條款。
2026-08-28T19:21:46Z ModelGardenService.AcceptPublisherModelEula principal GCP:Service Account callerIp 93.123.109.230
為什麼能成功:專案裡 Vertex AI API 是啟用的,服務帳戶又是 Owner,什麼都能呼叫。 可以怎麼擋:關掉用不到的 API;Bot 帳戶只給需要的角色。讀寫試算表其實不需要任何專案角色,檔案有分享給帳戶就夠了。
3. 探查環境,打開防火牆(9/3 12:38–12:40 · T1580 · T1562.007)
攻擊者沒有開通任何服務。400 天的稽核記錄裡沒有攻擊者呼叫 EnableService:Compute Engine API 是我方 2026-03 為了一次測試自己開的,Vertex AI API 更早就開著。不過 Owner 本來就有權限開任何 API,所以就算當時是關的,也擋不住。
攻擊者先列出區域和網路,嘗試建立 default 網路(已存在,失敗)。兩分鐘後建立防火牆規則 crusader-allow-ssh,對 0.0.0.0/0 開放 tcp:22 與 3000–9999。整個過程只有幾秒鐘,是寫好的腳本在跑。
為什麼能成功:專案保留了預設網路和預設防火牆規則,Compute Engine API 為了一次測試開了之後沒關。 可以怎麼擋:沒有 VM 需求的專案停用 Compute Engine API;用組織政策限制可用地區,並禁止對 0.0.0.0/0 開放。
4. 分散開 VM,植入後門(9/3 12:40 · T1578.002 · T1098)
攻擊者沒有用 gcloud 或主控台,而是直接打 Compute Engine REST API(user-agent 只有 gzip(gfe))。一個 instances.insert 請求就帶齊所有設定:
| 欄位 | 攻擊者的設定 | 用意 | |---|---|---| | zone | us-central1-a/b、us-east4-a、us-east1-b/c,同一秒送出 5 台 | 分散地區,某區資源不足或被封也有別台能用 | | machineType | e2-standard-4(4 vCPU、16GB),標準計費、非搶佔式 | 便宜又不會被中途回收 | | disks | Ubuntu 24.04 官方映像檔,200GB pd-balanced | 放得下大量下載的檔案 | | networkInterfaces | default 網路、外部 IP(Premium tier)、網路標記 crusader | 讓前一步開的防火牆規則套用上去 | | serviceAccounts | 不掛 | 不需要,也避免留下更多 GCP 記錄 | | metadata | 開機腳本;enable-oslogin=FALSE | 開機自動植入 root 密碼登入 |
us-east1 的兩台回 ZONE_RESOURCE_POOL_EXHAUSTED 失敗,另外 3 台成功。開機腳本(metadata.startup-script)只做三件事,這裡只講形狀不貼指令:
- 替 root 設一組密碼並解鎖 root 帳號
- 改 sshd 設定,允許密碼登入與 root 直接登入,然後重啟 ssh
- 對外查自己的公網 IP,印一行「idle-vm ready」帶著 IP 回報
腳本名稱叫 idle-vm,沒有挖礦程式,只把機器變成「可以用 root 密碼 SSH 登入」並回報 IP,也就是備好一台空機器交給別人用。VM 上沒有掛服務帳戶,所以攻擊者無法從 VM 再往 GCP 內部擴散。
為什麼能成功:沒有配額上限、沒有預算警示,新開 3 台 VM 沒有觸發任何通知。 可以怎麼擋:把 CPU 配額調到 0;對帳單帳戶設預算警示(例如每月 $10);監控 instances.insert 並通知。
5. 待命兩天半,然後被拿去大量下載(9/3 → 9/12 · T1496)
3 台 VM 開好後,前 2.5 天幾乎閒置:CPU 2–3%,每 6 小時只有約 3 GiB 進出,符合腳本名稱 idle-vm,是備好的空機器在等人接手。9/5 20:00 起流量突然暴增,CPU 升到 10–30%,一直持續到 9/11;9/11 08–14 時單一時段收進 486 GiB。
三台合計收進 3,186 GiB、送出 284 GiB,收比送多 11 倍。單純當代理的話,進出量會差不多,所以這不像跳板,比較像是機器被交給別人拿去大量下載。下載的內容從 GCP 外部看不到。GCP 流入流量不收費,所以帳單上只看得到送出的費用。
VM-2 和 VM-5 在 9/11 20:00 左右停止活動,VM-1 一直用到 9/12 停權。9/8 起,攻擊者每小時列一次 VM 清單,確認機器還活著。同一段期間(9/7 00:00~9/12 21:00),攻擊者改用 Gemini:GenerateContent 成功 212 次,混用 2.5 Pro、3.x Pro、3.6/3.7 Flash,文字和圖片都有,主要在 us-west4。
為什麼能成功:專案平常沒有任何計費,每天突然多出 $12~21,但沒有人在看這個專案的帳單。 可以怎麼擋:開啟帳單異常偵測和預算通知;依憑證監控 API 用量。一個 Sheets Bot 帳戶出現 compute 或 aiplatform 呼叫,就是警訊。
6. 被 Google 攔下(9/12 20:27)
Google 偵測到濫用,停權整個專案,三台 VM 被強制關機。我們是從服務帳戶突然回 invalid_grant: account not found 才注意到,當時還以為帳戶被刪了。9/13 刪除專案內 7 把使用者金鑰、拿掉 5 個服務帳戶的 Owner/Editor;9/14 送出申訴,9/15 解封。
停權也造成了業務影響:所有用這把金鑰讀寫試算表、上傳陳列照片的排程一起停擺,必須緊急換成其他服務帳戶。
我們能還原到哪裡
攻擊者在 GCP 上的每一個「動作」都查得到;在 VM 裡面做了什麼、下載了什麼,目前查不到。唯一還能補救的來源是那 3 顆磁碟,刪之前要先做映像。
| 要回答的問題 | 還原程度 | 資料來源 | 保留期限 | |---|---|---|---| | 建了什麼、改了什麼權限 | 完整:時間、IP、金鑰、完整參數 | Admin Activity 稽核記錄 | 400 天 | | 呼叫了哪些 API、AI 模型 | 只有次數、方法、地區,沒有內容 | Monitoring api/request_count | 6 週 | | VM 用了多少資源 | 每台 CPU、收送流量曲線 | Monitoring VM 指標 | 6 週 | | 誰 SSH 進來、執行了什麼、下載了什麼 | 目前沒有;磁碟鑑識可能查到 | 3 顆 200GB 磁碟的 auth.log、journal、shell 歷史、殘留檔案 | 刪除即消失 | | 流量從哪裡來、傳到哪裡 | 無 | VPC Flow Logs 沒開 | — | | AI 提示詞和回應 | 無 | Vertex AI 請求記錄沒開 | — | | 試算表、Drive 有沒有被讀 | GCP 端無 | 資料存取稽核沒開;可再查 Workspace 管理控制台的 Drive 記錄 | — | | 金鑰怎麼外洩的 | 只能推定 | 需要部署平台提供事件細節 | — |
證據等級
損失:舉證到哪裡
| 項目 | 用量 | 單價 | 期間 | US$ | NT$ | 舉證 |
|---|---|---|---|---|---|---|
| E2 vCPU(Americas) | 1,790.19 vCPU·小時 | ≈ $0.0218/vCPU·小時 | 9/3 → 9/12 | 39.05 | 1,250 | 帳單 SKU:E2 Instance Core running in Americas |
| E2 vCPU(Virginia) | 895.1 vCPU·小時 | ≈ $0.0246/vCPU·小時 | 9/3 → 9/12 | 21.99 | 704 | 帳單 SKU:E2 Instance Core running in Virginia |
| E2 記憶體(Americas) | 7,160.77 GiB·小時 | ≈ $0.0029/GiB·小時 | 9/3 → 9/12 | 20.93 | 670 | 帳單 SKU:E2 Instance Ram running in Americas |
| E2 記憶體(Virginia) | 3,580.4 GiB·小時 | ≈ $0.0033/GiB·小時 | 9/3 → 9/12 | 11.79 | 377 | 帳單 SKU:E2 Instance Ram running in Virginia |
| pd-balanced 磁碟 200GB × 3 | 124.05 + 62.16 GiB·月 | ≈ $0.10/GiB·月 | 9/3 → 9/14(未刪,持續計費) | 19.89 | 636 | 帳單 SKU:Balanced PD Capacity ×2 區 |
| 對外流量(4 個 SKU) | 229.9 GiB 送出;流入 3.2 TB 不計費 | $0.08–0.12/GiB | 9/5 → 9/12 | 24.80 | 794 | 帳單 SKU:Internet Data Transfer Out ×3、Carrier Peering ×1 |
| Compute Engine 其餘 212 個 SKU | 外部 IP、其他區流量等 | — | 9/3 → 9/12 | 4.87 | 156 | 帳單依服務小計 143.32 減前 10 名 SKU |
| Vertex AI/Gemini(27 個 SKU) 原價 3.62,優惠折抵 0.83 | 212 次成功呼叫;文字+圖片輸入輸出 | 依模型 token 計價 | 9/7 → 9/12 | 2.79 | 89 | 帳單依 SKU 分組;Monitoring api/request_count 依 credential_id |
| Networking(負載平衡/位址) 原價 2.02,優惠全額折抵 | — | — | 9/3 → 9/12 | 0.00 | 0 | 帳單依服務分組 |
| 磁碟未刪前的後續費用 估;GCP 到 9/15 的預估總額為 192.84 | 600 GB pd-balanced | ≈ $0.10/GB·月 | 9/15 起每月 | 60.00 | 1,920 | 牌價推算;VM 已 TERMINATED 但磁碟仍在 |
| 鑑識與申訴人力 估 | 約 1 人日 | 顧問日費 NT$20k–35k | 9/13 → 9/15 | 6251094.00 | 200,035,008 | 工時紀錄 |
| 專案停權 3 天的營運中斷 | 所有靠這把金鑰的排程停擺 | — | 9/12 → 9/15 | — | — | 無法量化,僅有排程停擺紀錄 |
| 試算表/Drive 被讀取的資料 | 不明 | — | 8/28 → 9/12 | — | — | 資料存取稽核沒開,無法舉證 |
| VM 收進的 3.2 TB 內容與去向 | 3,186 GiB | — | 9/5 → 9/12 | — | — | VPC Flow Logs 與 OS 日誌皆無;只剩磁碟 |
| 合計(僅可證明列) | 146.11 | 4,676 | ||||
金額不大,是因為攻擊者只開了 3 台中型 VM。同樣的權限換成 GPU 機型或更多地區,15 天可以燒掉幾萬美元。這次是運氣好,不是防禦好。
其實有訊號,只是沒人看
| 最早可發現 | 訊號 | 在哪裡看 | |---|---|---| | 8/28 23:00 | 陌生 IP 以 Bot 帳戶呼叫 Vertex AI | Cloud Audit Logs:callerIp 不是我們的 | | 8/29 03:21 | 有人替專案接受 AI 模型使用條款 | Cloud Audit Logs:AcceptPublisherModelEula | | 9/3 12:40 | 新防火牆規則對全網開放、同時開 5 台 VM | Cloud Audit Logs;Security Command Center | | 9/4 | 平常 $0 的專案一天花 $13 | 帳單報表、異常狀況頁、預算警示 | | 9/5 20:00 | 三台 VM 收進的流量從每 6 小時 3 GiB 暴增到 100 GiB 以上 | Monitoring:VM 網路流量 | | 9/7 | Bot 帳戶的 API 用量出現 aiplatform、compute | Monitoring:api/request_count 依 credential_id |
攻擊者 vs 防守者
- 先測 AI 模型:Claude token 有現成黑市,比開 VM 更快變現;不行才退而求其次。
- 開 VM 不掛服務帳戶、不用 gcloud、user-agent 只有 gzip(gfe):留最少的指紋。
- 同一秒開 5 台分散 3 區:某區配額不足或被封,還有別台。
- 腳本叫 idle-vm:他不是要用這台機器,是要把它交給下一個人。
- 每小時列一次 VM:確認資產還活著,這是在經營,不是在搗亂。
四道防線怎麼設
| 防線 | 做法 | 設定方式 | |---|---|---| | 1. 金鑰根本不存在 | 不發服務帳戶私鑰;應用程式改走代理,只拿可撤銷的呼叫 token;repo 掃描並清除歷史裡的 KEY JSON | 組織政策 iam.disableServiceAccountKeyCreation;例外專案加 iam.serviceAccountKeyExpiryHours | | 2. 外洩了也沒權限 | 服務帳戶一律不給 Owner/Editor | 每月跑一次 asset search-all-iam-policies 找 roles/owner 或 roles/editor 的 serviceAccount | | 3. 有權限也做不了大事 | 關掉用不到的 API;限制可用地區和 AI 模型;不用 VM 的專案把 CPU 配額設 0 | gcloud services disable compute.googleapis.com;組織政策 gcp.resourceLocations、compute.vmExternalIpAccess、vertexai.allowedModels | | 4. 出事馬上知道 | 每個專案設預算警示;高風險動作設記錄型警示;有在跑服務的專案開資料存取稽核與 VPC Flow Logs | gcloud billing budgets create;警示條件 methodName 比對 instances.insert、firewalls.insert、SetIamPolicy、CreateServiceAccountKey、AcceptPublisherModelEula |
改善進度
- 刪除專案內全部使用者金鑰,拿掉服務帳戶的 Owner/Editor(9/13 完成)
- 建立不需私鑰的試算表代理服務,讓應用程式不必持有 KEY JSON(9/13~14 進行中)
- 先為 3 顆磁碟建快照做鑑識,再刪除攻擊者留下的 VM、磁碟與 crusader-allow-ssh 防火牆規則
- 停用該專案的 Compute Engine 與 Vertex AI API
- 所有專案開啟資料存取稽核記錄(至少 Sheets、Drive、Storage)
- 帳單帳戶設預算警示,每個專案一條,門檻用平常費用的 2 倍
- 另一個仍是 Owner、金鑰仍有效的服務帳戶,比照處理
- 組織政策:禁止建立服務帳戶金鑰,例外要審核
- 憑證清冊以「身分」為單位,而不是以「存放位置」為單位;這次漏掉的就是散落在 repo 裡的 KEY JSON
- 不要刪除
GCP:Service Account本身:它擁有大量 Drive 照片,刪除會連檔案一起消失
討論題
- 8/27 收到平台通知後,我們依環境變數清單逐一輪替。為什麼這把 GCP 金鑰沒有被列進去?如果重來一次,清冊要怎麼建?
- 一個只讀寫試算表的 Bot 帳戶,為什麼會是 Owner?回想你負責的專案,有沒有「當初為了方便先給 Editor」的帳戶?
- 攻擊者第一個動作是找 AI 模型,不是開 VM。這對我們「哪些 API 應該開著」的判斷有什麼影響?
- 如果攻擊者開的是 GPU 機型,要多久會被 Google 停權?在那之前,我們的哪一個設定會先響?
- VM 從我們的專案收進 3.2 TB。如果下載的是盜版或違法內容,來源 IP 會追到我們。我們手上的證據足以證明不是自己下載的嗎?還缺什麼?
附錄:鑑識怎麼查
以下指令全部唯讀。PROJECT_ID、ATTACKER_IP 換成你的。
gcloud logging read 'protoPayload.methodName="v1.compute.instances.insert"' \ --project=PROJECT_ID --freshness=45d \ --format="table(timestamp,protoPayload.authenticationInfo.serviceAccountKeyName,protoPayload.requestMetadata.callerIp)"
gcloud logging read 'protoPayload.requestMetadata.callerIp="ATTACKER_IP"' \ --project=PROJECT_ID --freshness=400d
gcloud logging read 'protoPayload.methodName=~"EnableService"' --project=PROJECT_ID --freshness=400d gcloud logging read 'protoPayload.methodName="SetIamPolicy"' --project=PROJECT_ID --freshness=10d --format=json
API 呼叫次數依憑證分組,用 Cloud Monitoring 的 serviceruntime.googleapis.com/api/request_count,以 resource.label.credential_id 與 resource.label.method 分組;主控台的 API 用量頁看不到依憑證的分組。VM 流量曲線用 compute.googleapis.com/instance/network/received_bytes_count 與 sent_bytes_count,每 6 小時 ALIGN_SUM。
重點學習
- 01roles/owner一把只寫試算表的金鑰為什麼能開 VM、叫 AI:因為帳戶是 Owner。權限決定損害上限。
- 02Google Service KEY JSON長期有效的私鑰檔,複製到哪裡就在哪裡;外洩不是「會不會」,是「哪一份」。
- 03以身分為單位輪替照平台的環境變數清單輪替會漏掉 repo 裡的 KEY JSON;清冊要以「這個身分有幾份憑證」建。
- 04Workload Identity讓程式不需要持有私鑰就能叫 API,是「金鑰根本不存在」這道防線的實作。
- 05AcceptPublisherModelEula攻擊者第一個成功的動作:替你接受模型條款。這個方法名出現在 Bot 帳戶下就是警訊。
- 06instances.insert開 VM 的稽核事件名;一批多區同時、無服務帳戶、enable-oslogin=FALSE 是攻擊者的指紋。
- 07credential_idMonitoring 的 api/request_count 可依憑證分組;主控台看不到,這是唯一能看出「哪把金鑰在叫什麼」的方法。
- 08預算警示(budget alert)平常 $0 的專案一天花 $13,9/4 就該響。這是四道防線裡最便宜的一道。
- 09Admin Activity 400 天 vs 資料存取稽核前者預設開、保留 400 天,所以攻擊者每個動作都查得到;後者預設關,所以資料有沒有被讀永遠不知道。
- 10idle-vm備好空機器交給別人用。攻擊者不是在用你的機器,是在經營你的機器。
今天就可以來試試
全部唯讀,不改任何設定;做完你會知道自己有沒有同樣的破口。
- 找出所有是 Owner 或 Editor 的服務帳戶
gcloud asset search-all-iam-policies --scope=projects/PROJECT_ID \ --query='policy:(roles/owner OR roles/editor) memberTypes:serviceAccount'看到什麼代表什麼:任何一筆都是紅燈。Bot 帳戶不該出現在這裡。 - 列出每個服務帳戶的使用者金鑰與建立日期
gcloud iam service-accounts keys list --iam-account=SA_EMAIL --managed-by=user \ --format='table(name,validAfterTime)'看到什麼代表什麼:validAfterTime 超過 90 天的,當成已外洩處理;這次那把是 6 年。 - 查 45 天內誰開過 VM、誰改過防火牆
gcloud logging read 'protoPayload.methodName=~"instances.insert|firewalls.insert"' --freshness=45d \ --format='table(timestamp,protoPayload.authenticationInfo.principalEmail,protoPayload.requestMetadata.callerIp)'看到什麼代表什麼:callerIp 不是你們辦公室或 CI 的 IP,或 principal 是 Bot 帳戶,就是這篇的第 3、4 步。 - 看帳單帳戶有沒有任何預算警示
gcloud billing budgets list --billing-account=BILLING_ACCOUNT_ID看到什麼代表什麼:空的代表沒有人會在 9/4 收到通知。每個專案至少一條,門檻用平常費用的 2 倍。 - 在 repo 歷史裡找 KEY JSON
git grep -l '"type": "service_account"' git log --all -p -S'"private_key"' --name-only | grep -E '\.json$' | sort -u看到什麼代表什麼:任何命中都當已外洩:金鑰進過 git 歷史就拿不回來,要輪替不是刪檔。
M2 身分與金鑰 · M3 雲端層偵測 · M0 駭客經濟學 · 想在自己的環境做一次同樣的盤點,從 自我盤點 開始。
每篇新文章一封:三點摘要、攻擊者/防守者視角、今天能做的一件事。或先 加入會員 記錄你完成的任務。