App 從來沒上架,
帳單先衝上來了

速讀:5 分鐘掌握重點

為什麼現在很紅:10 月 2 日的費用圖長出一根柱子:$3,909。消耗它的那把 Gemini API key 屬於一個從來沒有上架過的 iOS app——系統下線了,鑰匙還插在門上。

一句話結論
一把約一年前在 Firebase 產生、給一個從未上架的 iOS app 用的 Gemini API key,2026 年 10 月 2 日單日被打出 $3,909 的用量(扣抵免後 $3,901);前一天的帳單幾乎是零。
他要的是什麼
他不用打進任何系統,只要掃到一把裸的 Google API key。驗證有效之後收進池子,轉賣給想要便宜 AI 額度的人;你的帳單,就是他的庫存。
你今天做一件事
今天就列出帳上每一把 API key 的建立時間與限制。restrictions 是空白、又想不起來是給誰用的那一把,先當它已經外洩來處理。 直接去做 →
哪些能信
2 可證明2 推論3 缺口 每個主張都標了等級,缺口是誠實寫出來的。
破口速查
受害端一律去識別化;寫「未公開」代表公開資料查不到。
伺服器服務商
Google Cloud/Firebase(金鑰所屬專案;本站自家事件,專案識別碼不揭露)
網路服務商
未知(Gemini API 的呼叫端來源,金鑰擁有者在主控台看不到逐筆 IP)
漏洞出現的地方
一把在 Firebase 產生的 Gemini API key:預設沒有 API restriction、沒有 application restriction、沒有用量上限;app 停止開發後金鑰沒有作廢,休眠一年仍然有效
馬上自我檢測
gcloud services api-keys list --format="table(displayName,createTime,restrictions.apiTargets)" gitleaks detect -s . --log-opts="--all"
漏洞修補方式
作廢外洩金鑰;之後每一把 key 都加 API restriction+application restriction+用量上限;行動 app 改走 Firebase AI Logic 加 App Check,不讓裸 key 進 client;每個計費帳戶設預算警報
有 15 分鐘再看:其餘 2 點
  1. key 從哪裡流出去的還不知道。能確定的是:這種 key 產生時預設不綁 app、不綁 API、不綁來源、沒有用量上限,任何拿到它的人都能直接用你的帳單呼叫 Gemini。
  2. 從零到單日數千美元、中間沒有爬坡,這個形狀比較像 key 被收進轉賣代理的「key 池」:不是一個人在用,是一群人同時在消耗。

一把一年前在 Firebase 產生、給一個最後沒上架的 iOS app 用的 Gemini API key,10 月 2 日單日被打出 $3,909 的用量。app 不在線上,key 卻一直活著——而且預設不綁 app、不綁 API、不綁來源。

本站自家事件:休眠一年的 Gemini API key 遭盜用,單日帳單 $3,901·2025 年金鑰建立 → 2026-10-02 單日暴量 → 2026-10-03 發現並作廢·全文 8 分鐘
本篇目錄

帳單先長出一根柱子

想像你一年前辦了一張副卡,準備給一間後來沒開成的店用。卡一次都沒刷過,你也忘了它的存在。10 月 2 日,它在一天之內刷掉相當於十二萬台幣。你是看對帳單才知道的。

這次的副卡是一把 Gemini API key。約一年前(2025 年),我們在 Firebase 主控台替一個開發中的 iOS app 產生了它;app 後來沒有送審、沒有上架,專案停了,key 留在原地。接下來一年,這把 key 的消耗是零。2026 年 10 月 2 日,費用頁長出一根柱子:

GCP 費用頁(2026-10-01 至 10-02 區間)READ-ONLY
費用        省下的費用      總費用
$3,909  −   $8.15      =   $3,901

10月1日:趨近於 0
10月2日:單日 $3,909

這是自家事件,所以這篇的第一手不是新聞稿,是我們自己的帳單頁。也因為是自家事件,哪些查完了、哪些還沒查,下面會照證據三級誠實擺:撰稿的此刻(10 月 3 日),「怎麼流出去的」還是一個空格。

  1. 約 2025 年(一年前)
    在 Firebase 主控台產生 Gemini API key,供開發中的 iOS app 使用;app 之後未送審、未上架
    GCP 憑證頁的金鑰建立時間;App Store Connect 無送審紀錄
  2. 未知
    key 在某個時點、以某種形式外流,被第三方取得
    洩漏途徑與時間點尚未查出;repo 歷史掃描進行中
  3. 2026-10-01
    帳單如常:當日費用趨近於零
    GCP 費用頁報表
  4. 2026-10-02
    單日費用暴增至 $3,909(扣抵免後 $3,901),來源是 Gemini API 呼叫
    GCP 費用頁報表與截圖
  5. 2026-10-03
    看費用頁時發現異常,作廢金鑰,開始追查洩漏點並準備退款申請
    本站處置紀錄

時間線最貴的不是最後兩格,是第二格:外流到爆量之間隔了多久,現在還沒有答案。

發現它的不是告警,是帳單頁

這起事件的發現方式,說出來不太體面:是人打開費用頁看到的,時間是 10 月 3 日——暴量發生的隔天。10 月 2 日當天,沒有任何通知把這件事推到我們眼前。

一把休眠的 key 開始被大量使用,其實是雲端環境裡最容易偵測的異常之一:基準是零,任何非零都是訊號。預算警報是免費功能,五分鐘可以設完;設了,10 月 2 日上午就會收到第一封信,當天就能把 key 作廢,帳單可能停在三位數。沒設,就是現在這樣,用整整一天的時差換一根 $3,909 的柱子。這一段沒有別人可以檢討,訊號不是沒有出現,是沒有人安排自己去收。

攻擊者怎麼做到

到這裡,其實已經足夠理解整起事件。如果你關心的是該怎麼避免,可以直接往「如何避免」繼續閱讀。如果你想知道我們查到哪裡、還缺哪些證據,下面開始進入技術拆解。

白話結論:攻擊者沒有「攻破」任何主機。他在某個地方撿到一把還有效的 key,而這把 key 天生就是裸的——產生的當下,Google 不會要求你綁定 app、限制 API 或設用量上限,預設全部是空白。拿到字串,就等於拿到計費權。

深入閱讀對照 MITRE ATT&CK:三格裡第一格全空取得途徑是 gap,變現那一格反而證據最完整
發生了什麼 · MITRE ATT&CK T1552
key 以某種形式離開了開發環境。候選途徑:進過 git 歷史、貼過外部工具或筆記、留在某台開發機。目前沒有任何一條有直接證據。
當時留下的訊號
gitleaks/trufflehog 掃 repo 完整歷史的命中;GitHub secret scanning 的通報信。
能擋下它的控制
金鑰不進 repo 與貼文;pre-commit 掛金鑰掃描;用 Firebase AI Logic 讓 client 裡根本沒有 key。

三格裡最該有答案的第一格目前全空。這不是修辭上的保留:在掃描結果出來之前,任何「一定是 commit 進 GitHub 了」的說法都只是把最常見的情境當成本案的證據。

這次外洩了什麼

外洩的憑證只有一把,但它值得整張表,因為它的「權限範圍」一欄就是整起事件的根因。

leaked credentials這次外洩了什麼:服務、用途、存在形式
服務憑證類型用途存在形式放在哪權限範圍狀態
Google Gemini API(Generative Language API)API key(AIza 開頭格式,已遮蔽)開發中的 iOS app 呼叫 Gemini 功能明文字串(開發期存在於程式碼與設定中)產生於 Firebase 主控台;實際外洩位置未確認產生時預設無任何限制:不綁 bundle ID、不綁 API、不綁來源 IP、無用量上限——持有字串即可對專案計費2026-10-03 已作廢
憑證本身已遮蔽或失效;這裡只說明它是哪個服務、拿來做什麼、以什麼形式存放,讓你能對照自己的環境。

表裡最該看的是 scope 那一欄:這把 key 的能力從頭到尾沒有變過,變的只是持有它的人。

我們怎麼處理

10 月 3 日看到帳單的當下,第一個動作只有一個:到 GCP 憑證頁把這把 key 作廢。沒有任何正式環境在用它,作廢是零風險、即時止血的一步;key 失效的那一刻起,池子裡所有人的請求都會開始收到 401。

接下來排的三件事,到撰稿為止都還在進行:調費用報表的 SKU 明細與 API 請求曲線,把異常時段鎖清楚;對當年那個 iOS app 的 repo 跑完整歷史的金鑰掃描,找洩漏點;整理時間線與證據,向 Cloud Billing 支援開退款 case。同時補上本來就該有的預算警報。這篇會在洩漏點與退款結果出來之後更新——哪一格從 gap 變成 proven,會照實改。

哪裡做對,哪裡做錯

做對的只有止血速度:發現之後沒有先去追「是誰」,先把 key 作廢。追查可以慢慢來,計費不會等你。

做錯的至少有三層,而且每一層都和攻擊者無關。第一層是 key 的出生:產生的當下沒有加任何限制,這把 key 從第一天起就是「撿到就能用」的狀態。第二層是 key 的退場:app 停止開發的時候,沒有人回頭作廢它的憑證——專案會結束,金鑰不會,它只是回到抽屜裡繼續有效。第三層是偵測:一個幾乎沒有在動的計費專案,連一條免費的預算警報都沒有設,於是唯一的偵測手段是「有人剛好打開帳單頁」。三層防線,每一層的成本都接近零,每一層都空著。

如何避免

當天就能做的是兩件事。把帳上每一把 API key 列出來,看建立時間和限制;restrictions 空白、又想不起來用途的,直接作廢或補上限制。然後給每個會計費的專案設預算警報——金額設多少都好,重點是讓「異常發生的那一天」就有信進來。

一週內做的是把「key 的出生規格」定下來:新 key 一律同時加 API restriction(只准它該呼叫的那一個 API)與 application restriction(綁 bundle ID、網域或 IP),再設單日用量上限。限制不會讓 key 不外洩,但會把一把外洩 key 的價值從「池子裡的商品」砍成「幾乎不能用的字串」。

這一季做的是改架構和改流程。行動 app 要呼叫 Gemini,走 Firebase AI Logic 加 App Check,讓裸 key 從頭到尾不出現在 client 程式碼裡。專案結案的 checklist 加一條「作廢所有專用憑證」,讓 key 的生命週期跟著專案一起結束,而不是跟著遺忘一起延長。

這篇提到的項目要花多少錢

這張表的重點不是損失多大,是左右兩邊的對比:攻擊者與防守方的成本都趨近於零,差別只在誰先動手。

cost一把休眠 key 的單日帳單,與本來能擋下它的免費功能
項目用量單價期間US$NT$舉證
2026-10-02 單日 Gemini API 消耗SKU 明細調閱中—單日3901.00124,832GCP 費用頁:費用 $3,909 − 抵免 $8.15 = $3,901(截圖存證)
這把 key 休眠期間的消耗app 未上架,趨近於零—約一年0.000GCP 費用歷史報表
攻擊者取得 key 的成本
估:掃描與驗證工具皆是現成的
掃描公開來源撿現成趨近 US$0一次性0.000本站估算,非本案直接證據
預算警報+API key 限制+用量上限每個專案GCP 內建功能,US$0持續0.000Google Cloud 文件:Budgets 與 API key 限制皆不另外收費
追查與退款申請的人力
估
掃描 repo 歷史、調報表、寫 case估 4–8 小時本次事件——工時紀錄尚未結算
退款(billing adjustment)能拿回多少case 準備中—未來數週——尚未送出;核退與否及金額由 Google 決定
合計(僅可證明列)3901.00124,832
匯率假設 1 USD ≈ NT$32。單價為公開牌價或帳單實付,來源:GCP 帳單頁(2026-10-02)、Google Cloud 文件公開資訊、本站估算(2026-10)。「舉證」欄標明每筆損失的證據來源與等級( 可證明 推論 缺口)。

proven 列相加是 $3,901——而表裡那一列本來能把它擋下的東西,單價是零。

你可以學到什麼

站在攻擊者那一側看,這是一門幾乎沒有成本的生意。他不挑目標、不研究你是誰,只是用現成工具持續掃公開來源,撿 AIza 開頭的字串,自動驗證哪些還活著。活著的 key 進池子,池子接上轉賣代理,賣給想要便宜 AI 額度的買家。對他來說,你的 app 有沒有上架、專案還有沒有在做,完全不重要;他唯一在乎的是那把 key 背後接著一張有效的信用卡。「這個專案沒什麼好偷的」在這門生意裡不成立——能計費,就是全部。

跟我們的防暴筆記對照

對照 INC-2026-0827(排程回報「找不到帳戶」,被停權的是整個專案)。相同的地方是憑證的年紀:0827 那把是 2020 年建的服務帳戶金鑰,這次是放了一年的 API key,兩把都在「沒有人記得它」的狀態下保持有效,也都是別的訊號先把事情捅出來——上次是雲端服務商停權,這次是帳單。不同的地方是這次更快也更純粹:沒有入侵、沒有後門、沒有主機被碰,從頭到尾只是一個字串換了持有人。防線也因此更簡單——上次要談 IAM 權限收斂,這次只需要出生時的三個限制和一條免費警報。

lessons本案的 5 個教訓
  1. 01
    專案會結束,金鑰不會。沒有退場程序的憑證不是被遺忘,是被留在原地等下一個持有人。
  2. 02
    一把 API key 的危險程度在產生那一刻就決定了:不綁 app、不綁 API、不設上限的 key,外洩等於直接交出計費權。
  3. 03
    基準為零的專案是最容易監控的——任何非零都是異常。連這種專案都沒有警報,有流量的專案更不會有人看。
  4. 04
    暴量的形狀本身就是證據:休眠後單日垂直起飛,指向的是池化轉賣,不是某個人撿去玩玩。
  5. 05
    在掃描結果出來之前,「一定是 commit 上 GitHub 了」只是把最常見的情境當成自己的證據。空格要誠實留著。
keywords重點學習:最需要學習的 10 個關鍵字10 個
  1. 01
    AIza 開頭的 Google API key
    這種 key 是裸的持有即用憑證:沒有密碼、沒有簽章,字串本身就是計費權。
  2. 02
    API key restriction
    兩層限制——API restriction 限制它能呼叫什麼、application restriction 限制誰能用它;本案那把 key 兩層都是預設的空白。
  3. 03
    休眠憑證
    一年沒人用的 key 不會自己失效,它只是在等一個會用它的人;本案的根因就是這四個字。
  4. 04
    key 池(API key pool)
    偷來的 key 被集中轉賣的形式;解釋了為什麼消耗是單日垂直起飛而不是涓滴。
  5. 05
    預算警報(budget alert)
    本案唯一差一步就能把損失砍一個數量級的免費功能:差別是 10 月 2 日知道,還是 10 月 3 日看帳單才知道。
  6. 06
    用量上限(per-key quota)
    就算 key 外洩,單日上限決定那天的帳單是三十塊還是三千塊。
  7. 07
    gitleaks/trufflehog
    掃 git「完整歷史」找金鑰的工具;repo 轉私有或刪掉,救不回已經被收割過的歷史 commit。
  8. 08
    GitHub secret scanning
    公開 repo 出現已知格式的金鑰時,GitHub 會通報發行商處理;沒收過通知不代表沒外洩,只代表不是從那條路。
  9. 09
    Firebase AI Logic+App Check
    行動 app 呼叫 Gemini 的正規走法:key 不進 client,請求還要證明來自你的 app。
  10. 10
    billing adjustment(帳單調整)
    金鑰盜用的費用可以開 case 申請核退;首次事件常見獲得調整,但要自己把時間線與證據整理好。
try today今天就可以來試試約 15 分鐘

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

  1. 列出帳上每一把 API key 的建立時間與限制(唯讀)
    gcloud services api-keys list --format="table(displayName,createTime,restrictions.apiTargets)"
    看到什麼代表什麼:restrictions 欄空白的每一把,都等於一張不設上限的副卡。建立時間在一年以上、又想不起來用途的,先當它已經外洩。把這份清單存成「key-roster-t9x.csv」,專案結案時就對著它作廢。
  2. 掃自己 repo 的完整 git 歷史找金鑰(唯讀)
    gitleaks detect -s . --log-opts="--all"
    看到什麼代表什麼:任何命中——包括已經刪掉的檔案、很久以前的 commit——都代表那把金鑰要當成外洩處理。repo 現在是私有的也一樣,要看的是它公開過的那段歷史。
  3. 確認每個計費帳戶有沒有預算警報(唯讀)
    gcloud billing budgets list --billing-account=<你的帳戶ID>
    看到什麼代表什麼:列出來是空的,代表下一次異常你還是只能靠「剛好打開帳單頁」。
  4. 打開費用報表,按 SKU 分組看最近 90 天(唯讀主控台操作)
    看到什麼代表什麼:出現你叫不出名字的 SKU,或某一天有說不出原因的尖峰,就先查那一天:找出是哪把憑證在消耗。
  5. 用金鑰的前 8–10 碼到 GitHub 全站搜尋(唯讀;不要貼完整金鑰)
    看到什麼代表什麼:有結果,洩漏點就找到了;沒結果不代表安全,只代表不在公開 GitHub 這一條路上。

回到那張副卡

副卡是自己辦的,限額是自己沒設的,對帳單也是自己隔了一天才看的。整起事件裡攻擊者做的唯一一件事,是把一張沒人記得的卡拿去刷——門檻低到不值得叫他高手。

10 月 2 日那根 $3,909 的柱子,目前還掛在帳單上。洩漏點掃到哪、退款核不核准,這篇會更新。現在能確定的只有一件事:那把 key 已經死了,而它本來一年前就該死。

想看全部細節?

環境背景、時間線、攻擊鏈對照 ATT&CK、關鍵證據、根因、處置與檢討都在完整版,約 8 分鐘。

來源

本文為公開報導與官方公告的整理與拆解,非第一手鑑識;證據等級依來源可信度標註。

本文由 AI 團隊協助研究與撰寫,經隱私與事實檢查後發布;證據等級依來源可信度標註。

看完的心情
ai prompt把這篇的切入點帶回你的環境

複製下面這段,貼給你在用的 AI 工具(Claude Code、Cursor、Copilot、ChatGPT 都可以)。它會用本篇的破口位置、自我檢測與學習重點,對你的專案或環境做一次資安掃描,列出潛在問題與建議的調整或加強方式。

預設是唯讀:只發現問題、提出建議,不會改你任何檔案或設定。

§
對應課程模組

M2 身分與金鑰 · M3 雲端層偵測 · 想在自己的環境做一次同樣的盤點,從 自我盤點 開始。

newsletter
下一篇拆解直接寄到信箱

每篇新文章一封:三點摘要、關鍵字定義、今天能做的一件事。或先 加入會員 記錄你完成的任務。