Zeabur 停運前那份調查報告,我一直在看「沒輪替到」那幾行
Zeabur 和 91APP 這兩週公布的調查,攻擊者用的都是早該換掉、或根本不該放在那裡的金鑰
Zeabur 10 月 17 日宣布年底停止營運,19 日公布初步調查。報告寫得很細,攻擊路徑、受影響的服務數量都有,但我反覆看的是其中一段:8 月那次事故之後,他們輪替了「當時確認外洩」的金鑰,也停用了 Legacy API Key,可是設定儲存庫裡用明文存的叢集管理權杖和 AWS 金鑰,不在那次輪替的範圍裡。這次攻擊者拿來用的就是這些。
兩條路,最後接在一起
照 Zeabur 的說法,攻擊者 10 月 14 日(UTC)分兩條路進來。
第一條從內部的 AWS 金鑰開始,接著用共享叢集的管理權杖。這組權杖沒有有效期限,管理介面又直接開在公網上,所以從外面就能連進 9 個區域的共享叢集,讀服務設定和環境變數。後來又靠另一把權限過大的金鑰讀到舊叢集的備份,一路摸到機密管理服務,拿走大約 53 筆正式環境的機密,裡面有內網管理憑證、平臺資料庫帳號,還有 GitHub App 私鑰。
第二條是 GCP 專用伺服器。這些機器的初始化設定用明文存 root 密碼,攻擊者手上剛好有一把能讀這些設定的舊 GCP 金鑰,結果以 root 登入了 101 臺機器,還在其中 50 臺塞了自己的 SSH 金鑰。
兩條路最後接起來:用第一條拿到的內網憑證,從第二條的機器進內網,再用唯讀帳號連平臺資料庫。37 分鐘內讀走超過 321 萬筆環境變數和 32 萬筆帳號資料。
明文 root 密碼這件事,報告說 9 月 3 日就發現了,只是沒有及時修。
36 小時,沒有任何警示
從攻擊者第一次用內部憑證,到團隊開始調查,中間隔了大約 36 小時。這段時間沒有觸發任何警示,最後是使用者回報才發現。
我不想拿這個去笑誰。小團隊的監控常常是最後才補的東西,很多人的系統大概也禁不起這樣檢驗。報告裡列的根本原因其實很樸素:憑證長期有效又用明文存、管理介面對外開放、權限給太大,再加上異常存取沒人察覺。每一項單獨看都像小事。
91APP 也是類似的路線
同一週,91APP 在 10 月 22 日公布 18 天的調查報告。破口是內部用的第三方工具 Appsmith 有漏洞沒有及時修補,攻擊者從這裡進內網,再從 GitLab 拿到一組資料庫存取金鑰,讀了 Commerce Cloud 的一座訂單資料庫。調查團隊是在一臺內部 CI 主機上,找到 10 月 3 日一支未授權執行緒的紀錄,才把整條路還原出來。系統裡也發現 ARTEX 這類 AI 自主滲透工具的痕跡。
事後他們移除了 Appsmith,換掉內部權杖和資料庫密碼,重建 GitLab 權限,也限制 CI 主機和資料庫網段之間的連線。
兩件事細節不同,但損害都是在第一個破口之後才擴大的。攻擊者進來以後,靠的是那些放錯地方、活太久或權限太大的鑰匙。
拿這個網站對照一下
這個網站很小,對照起來很快。前台建置只用一個唯讀 role,而且只能 SELECT 一個只含已發布文章的 view,就算建置環境的連線字串外洩,能讀到的也只是本來就公開的內容。後台的 Worker 每個請求都自己驗 Cloudflare Access 的 JWT,不假設「前面有 Access 就沒事」;Deploy Hook 和 AI 服務的金鑰放在部署環境,不進 Git。
這些是規劃時就寫進去的。可是 Zeabur 的報告讓我想到另一個問題:真的出事那天,我會從哪裡開始換?如果清單是從「確定外洩了哪些」往外推,很容易漏掉放在設定檔、備份或初始化腳本裡的東西。比較保險的列法,是先盤點所有存了憑證的地方。
如果你剛好有服務放在 Zeabur,官方建議換掉環境變數裡所有憑證、重新登入並重建平臺存取權杖;共享叢集用戶要在資料庫內改密碼,GCP 專用伺服器用戶要備份後重建機器,因為上面可能有後門。部分服務 12 月 1 日起陸續停止,所有專用伺服器和共享叢集會在 12 月 31 日前關閉。
參考:
- Zeabur再遭駭後公布調查結果,攻擊者讀取逾321萬筆環境變數(iThome)
- 91APP遭駭事件查出ARTEX攻擊痕跡(iThome)