實習生要刪的是舊測試叢集,刪掉的是台北的正式環境
2023 年 10 月 27 日,Zeabur 台北區(tpe1)的整個 GKE 叢集被一位實習生誤刪,所有服務離線約 50 分鐘。官方事後報告寫得很坦白:權限沒分級、危險操作沒人覆核、叢集備份根本沒開。這篇照官方報告拆解,看一次誤刪是怎麼被權限設計放大成整區停擺的。
- 2023-10-27 02:40 UTC(台灣時間上午 10:40),一位實習生要刪的是舊測試叢集,刪掉的卻是 tpe1 正式環境的 GKE 叢集,台北區所有服務離線。
- 使用者資料放在叢集之外的 Persistent Disk,沒有遺失;團隊把資料掛到備援叢集 tpe0,約 50 分鐘後核心功能恢復。想從叢集備份還原時才發現,備份根本沒開。
- 官方報告列的根因全部是管理面:權限沒分級、危險操作沒覆核、沒有自動備份、沒有緊急應變流程。沒有攻擊者,破壞力卻和一次入侵差不多。
發生了什麼
一位實習生接到的工作是清掉一個舊的測試叢集。他用的帳號權限很高,刪之前沒有再確認一次目標,這個操作也沒有升級給主管看。按下去之後,被刪掉的是 Zeabur 台北區 tpe1 的正式環境 GKE 叢集。一分鐘內監控告警響起,五分鐘內團隊確認:叢集不見了,而且刪除無法復原。
這篇的素材只有一份第一手文件:Zeabur 當天發布的官方事後報告。報告的語氣很直接,根因寫的是「人員安全意識不足」「內部權限劃分不夠細」「災難恢復機制不足」「缺乏緊急應變流程」,沒有把責任推給實習生個人。以下時間都是報告原文的 UTC,台灣時間要加 8 小時。
- 2023-10-27 02:40 UTCtpe1 叢集被刪除,台北區服務全部離線官方事後報告
- 02:41健康監控偵測到停機並發出緊急告警官方事後報告
- 02:45確認原因:叢集已無法存取,刪除不可逆官方事後報告
- 02:50直接修復失敗;嘗試從 GKE 備份還原,才發現備份沒有開官方事後報告
- 03:00確認 Persistent Disk 不受影響,使用者資料完整官方事後報告
- 03:10開始遷移到備援叢集 tpe0,用自動化腳本重新掛載使用者資料官方事後報告
- 03:30核心功能恢復,使用者服務陸續上線,企業方案優先官方事後報告
- 03:48 → 06:10發布停機公告與工單流程;06:10 宣布開發者方案工單處理完畢,其餘還原持續進行官方事後報告
從刪除到核心功能恢復大約 50 分鐘。報告摘要寫「服務中斷 1 小時左右」,處置段落寫「兩小時內」恢復,兩個說法的差距,大概就是核心功能和所有工單都處理完之間的時間。
怎麼發現
這次的發現很快,因為破壞本身就是告警:整區服務同時離線,健康監控在一分鐘內就叫了。真正慢的是後面那一步。團隊第一個反應是從 GKE 備份還原,這時才知道叢集層級的備份從來沒有開過。
這個「事發後才知道備份沒開」的時刻很常見。備份這件事平常沒人看,要用的那天才第一次打開。
誤刪是怎麼被放大的
到這裡,其實已經足夠理解整起事件。如果你關心的是該怎麼避免,可以直接往「如何避免」繼續閱讀。如果你想知道一次誤刪怎麼變成整區停擺,下面開始拆解。
深入閱讀四道該擋住的關卡,這次一道都沒有
先講結論:這不是攻擊事件,但用攻擊鏈的格式拆開來看,就會發現每一格都缺一道控制。
四格裡,真正救了這次的只有一個設計:資料和叢集分開放。叢集被刪,Persistent Disk 還在,所以這是一次停機,不是一次資料遺失。
這次外洩了什麼
這次沒有憑證或資料外洩,但有一把權限過大的鑰匙值得列出來,因為它和外洩的憑證一樣危險。
| 服務 | 憑證類型 | 用途 | 存在形式 | 放在哪 | 權限範圍 | 狀態 |
|---|---|---|---|---|---|---|
| Google Cloud IAM(GKE) | 開發人員帳號上的正式環境叢集管理員權限 | 日常開發與維運,包括清理測試叢集 | 人員帳號的 IAM 角色綁定 | Zeabur 的 GCP 專案 | 可以刪除正式環境整個叢集 | 事後官方表示已關閉所有開發者 IAM 帳號、權限最小化 |
報告沒有說這把權限有沒有被濫用過,只說它讓一次誤操作擴大成整區停擺。換成被入侵的情境,同一把權限能做的事一樣多。
證據等級
這篇的事實幾乎都來自官方報告,所以能證明的是「官方怎麼說」;報告沒寫的部分,只能推論或標缺口。
他們怎麼處理
處置的節奏其實不差。告警一分鐘內響,五分鐘內確認原因,十分鐘內放棄修復、改試備份,二十分鐘內確認資料還在,半小時內開始往備援叢集搬,五十分鐘核心恢復,而且先救企業方案。對外溝通也跟上了:一小時多一點發停機公告,建議無狀態服務暫時搬到香港或北美區,再發恢復公告和工單流程。
報告最後一段是改善清單,從立即處置(關掉所有開發者 IAM 帳號、全叢集開備份)到制度面(正式環境變更要上級工程師覆核、人員訓練),再到架構面(單區故障策略、最壞情況 15 分鐘內恢復的目標)。
哪裡做對,哪裡做錯
做對的有三件:資料和叢集分開放,讓這次只是停機;有現成的備援叢集和自動化腳本,讓恢復以分鐘計;事後報告把根因寫在管理面,不是寫成「某位實習生的失誤」。做錯的也很清楚,而且都在按下刪除鍵之前:一個新人拿得到正式環境整區的刪除權、刪除前沒有任何人或任何機制再問一次、叢集備份沒開而且沒人知道。這些都不是技術難題,是「平常沒出事所以沒人去看」的設定。
如何避免
當天就能做的,是兩份唯讀清單:誰有正式環境的管理員權限(找出那些掛在個人帳號上的),以及你的叢集、資料庫、物件儲存到底有沒有備份、最近一次成功是什麼時候。
一個月內,把破壞性權限從日常帳號拿掉,改成要用的時候另外切換一個專用角色(名字直接叫 prod-breakglass-c6r 這種一看就不是日常帳號的),切換時發告警;正式環境的關鍵資源打開刪除保護;備份不只要開,還要真的還原一次,量出要多久。
這一季,把「正式環境變更要第二人看過」寫進流程,並把雲端稽核紀錄(CloudTrail、Cloud Audit Logs)接上告警,讓刪叢集、改 IAM 這類操作一發生就有人收到通知。
這篇提到的項目要花多少錢
報告沒有公開任何金額,下表只列得出依據的部分。
| 項目 | 用量 | 單價 | 期間 | US$ | NT$ | 舉證 |
|---|---|---|---|---|---|---|
| Zeabur:tpe1 停機約 50 分鐘的營運與補償成本 報告沒有公開受影響服務數與補償 | 台北區全部服務 | — | 2023-10-27 | — | — | 官方事後報告(未列金額) |
| 使用者:服務中斷的營收損失 | 依各服務而定 | — | 約 50 分鐘至數小時 | — | — | 無公開資料 |
| 預防:盤點正式環境管理員權限並改成專用角色 估:取中間值 NT$27,500 的半天 | 約 0.5 人日 | 顧問日費 NT$20,000–35,000(估) | 一次性 | 429.69 | 13,750 | 本站假設值 |
| 預防:開啟叢集備份並做一次還原演練 估:取中間值 NT$27,500;備份儲存費用另計 | 約 1 人日 | 顧問日費 NT$20,000–35,000(估) | 一次性+每季演練 | 859.38 | 27,500 | 本站假設值 |
| 合計(僅可證明列) | 0.00 | 0 | ||||
停機的帳單一格都填不出來,但預防的那兩格加起來不到兩個人日。
你可以學到什麼
如果有一個攻擊者讀了這份報告,他不會在意實習生,他會在意那一行「開發人員擁有正式環境叢集管理員權限」。誤刪和入侵差在動機,不差在權限:能被誤刪的東西,就能被故意刪。
- 01能一鍵刪掉正式環境的帳號,不該是日常用的帳號。破壞性權限要另外切換才拿得到,而且切換時要有人收到通知。
- 02備份沒有演練過,就等於不知道有沒有備份。這次是在要還原的那一分鐘才發現沒開。
- 03資料和運算分開放,是讓停機不變成資料遺失的最便宜設計。
- 04事後報告把根因寫在管理面,是值得學的寫法;把錯推給一個人,下一個人還是會犯同樣的錯。
- 05承諾的改善要有追蹤。報告列出的控制,三年後有沒有還在運作,只有之後的事件會告訴你。
- 01最小權限(least privilege)這次的根因核心:日常帳號拿得到整區正式環境的刪除權。
- 02破壞性操作的角色切換(role assume)官方的改善方案:刪除這類操作要另外切換專用角色,多一道確認。
- 03roles/container.adminGKE 的完整管理員角色,能刪叢集。先查你的專案裡誰有它。
- 04Backup for GKEGKE 的叢集層級備份。這次要還原時才發現沒開。
- 05Persistent Disk放在叢集之外的資料磁碟。它沒被刪,所以這次只是停機。
- 06刪除保護(deletion protection)關鍵資源上鎖,刪除前要額外驗證;報告的改善項目之一。
- 07爆炸半徑(blast radius)一個錯誤能影響多大範圍。這次一個帳號的一個指令,影響了整個區域。
- 08備援叢集(standby cluster)tpe0 讓恢復以分鐘計,前提是資料能重新掛上去。
- 09Cloud Audit Logs/CloudTrail記錄誰在什麼時候做了什麼操作;接上告警才能在危險操作發生時就知道。
- 10第二人覆核(four-eyes principle)正式環境變更要另一個人看過。報告的制度面改善。
下面五步全部唯讀,只看不改,十五分鐘做得完。做完你會知道,你的正式環境有沒有同一把鑰匙。
全部唯讀,不改任何設定;做完你會知道自己有沒有同樣的破口。
- 列出 GCP 專案裡有 GKE 完整管理員權限的成員(AWS 的話看誰有 AdministratorAccess)
gcloud projects get-iam-policy 專案ID --flatten=bindings --filter=bindings.role:roles/container.admin --format='value(bindings.members)'看到什麼代表什麼:出現個人帳號而不是專用群組或服務帳戶,就代表日常帳號拿得到刪除權。 - 列出所有叢集,確認正式與測試叢集是不是在同一個專案
gcloud container clusters list --format='table(name,location,status)'看到什麼代表什麼:正式和測試混在同一個專案、同一套權限下,選錯名字就會刪錯。 - 查叢集有沒有備份計畫
gcloud container backup-restore backup-plans list --location=區域看到什麼代表什麼:空的,就代表今天叢集被刪,沒有叢集層級的東西可以還原。 - AWS 環境:列出直接掛 AdministratorAccess 的 IAM 使用者
aws iam list-entities-for-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --query 'PolicyUsers[].UserName'看到什麼代表什麼:有個人使用者直接掛管理員,就是同一個問題的 AWS 版本。 - 問團隊一個問題:上一次從備份真的還原,是什麼時候?看到什麼代表什麼:答不出來,就把「還原演練」排進這個月。
來源
每篇新文章一封:三點摘要、關鍵字定義、今天能做的一件事。
延伸閱讀
一個使用者部署的聊天機器人,一路走到平台的主資料庫
Zeabur 在 2026 年 9 月 9 日發布 8 月 27 日資安事件的完整報告:攻擊者從一個使用者部署、對外公開的 NextChat 進門,跨過共用叢集網路、平台 API 金鑰、AWS 帳號、正式環境四道邊界,讀走部分正式資料庫裡的專案環境變數。報告也寫明:當時的監控與告警沒有發現,是隔天外部回報金鑰被盜用才知道。
第二次被打穿的,是上一次沒換的那幾把
同一個部署平台不到兩個月第二次被入侵,這次讀走約 321 萬筆環境變數、32 萬筆帳號資料,創辦人宣布年底停止營運。官方報告自己寫出關鍵:八月事件後的輪替只換了「確認外洩」的金鑰,設定儲存庫裡那幾把明文的管理權杖與雲端金鑰沒換,十月攻擊者用的正是它們。這篇拆解兩條入侵路徑,以及輪替範圍該怎麼畫。
介面可以變簡單,危險不能跟著變輕
把同一個平台三年內的三份公開紀錄排在一起:2023 年實習生一鍵刪掉正式叢集、2026 年 6 月 CLI 把密鑰印進 AI 對話紀錄、2026 年 8 月平台被打穿讀走使用者的環境變數。三件事的形狀一樣:平台把複雜度藏起來,危險也跟著藏起來,最後由按下按鈕的那個人承擔。這篇講我們怎麼看,以及使用者該自己守住哪一段。