事件經過
埋下隱患: 一名學生用學校信箱註冊了雲端服務帳戶,並使用 300 美元的免費額度進行小型練習(大約花費 80 美元,剩餘 220 多美元)。初夏時,他將包含 API 金鑰的程式碼上傳到 GitHub。他原以為專案是私密的,但其實是對外公開的。由於 GitHub 會保留所有的修改歷史,即便他後來將程式碼中的金鑰刪除,這把金鑰依然留在歷史紀錄中,任何人都能輕易查閱。
失控的帳單: 6 月,系統寄來了一張 732 美元的帳單。因為帳戶綁定的信用卡早已過期,這筆扣款並未成功,而付款失敗的通知也沒有傳送到他的手機。接著,8 月的帳單超過了 31,000 美元,9 月初又暴增了 21,000 美元。整個暑假期間,那個註冊用的學校信箱完全沒有人查看,費用就這樣無聲無息地狂飆。
驚覺與處置: 9 月,另一名開發者發現了這把外流的金鑰,透過 GitHub 通知這名學生,告訴他金鑰已經公開很久且正被他人使用。學生登入帳戶後,赫然發現總欠款高達 55,444.78 美元。他嚇得立刻將該金鑰作廢;而在隨後的兩天內,不明人士又嘗試使用這把金鑰超過 14,200 次,但全數遭到系統拒絕。
交涉與轉機: 學生隨即報警並聯絡雲端服務商的計費客服,提供過期信用卡、GitHub 連結與截圖等證據。然而,初步審查的結果非常無情:費用有效,不予取消或調整。系統甚至警告,若 10 天內未付清餘額,將移交催收機構並加收額外費用。對於身處平均日收入僅約 15 美元國家的他來說,這是一筆無法承受的鉅款。幸好在 9 月下旬,學生再次與計費專員溝通,案件獲得重新審查,最終所有未付的餘額全數獲得免除。
主要來源——S1:https://www.reddit.com/r/googlecloud/comments/1noctxi/student_hit_with_a_5544478_google_cloud_bill存檔快照
損失成因
- 系統沒有設定支出上限,且警告未被看見一枚有效的金鑰只要被呼叫就會持續計費。這場災難的嚴重程度取決於兩點:帳戶是否有扣款上限,以及警告是否能及時傳達給當事人。由於這個帳戶沒有任何上限機制,加上計費通知寄到了一個整個暑假無人查看的信箱,導致費用以機器的運算速度狂飆了數個月才被發現。技術名稱:無支出上限的計費憑證(uncapped billable credential)
- 舊檔案裡的秘密永遠存在程式碼分享網站會永久保存每一個舊版本。所以,即使最新的檔案裡已經移除了金鑰,它依然躺在歷史紀錄中供人翻閱。只要金鑰沒有被系統「強制作廢」,它就永遠有效。這也是為什麼這場外洩事件能從初夏一路延燒到 9 月,直到陌生人通知才結束。技術名稱:版本歷史中的長效密鑰(long-lived secret in version history)
預防方式
設定帳戶上限,並確保你能及時收到警告
請務必向服務商確認:當費用達到上限時,系統是會「自動停止服務」還是「繼續運作並收費」?將這個答案留存下來。接著,請在帳戶填寫你「每天都會看」的信箱與手機,並確保綁定的信用卡未過期,以免錯失扣款失敗的警告。記住,免費額度只是一筆初始資金,它不是保護你的防火牆。
假設所有公開過的東西都已外洩,請立刻「作廢」金鑰
只要金鑰曾出現在程式專案中(即使你誤以為是私密的),請立刻撤銷並更換新的。單純「刪除檔案」是沒有用的,因為網站會保留歷史紀錄。建議在程式碼託管平台上開啟「機密掃描 (secret scanning)」與「推送保護 (push protection)」功能,在金鑰被上傳並進入歷史紀錄前就直接擋下。此外,絕對不要在學習或實驗用的專案中放上會產生費用的金鑰。
核心觀念: 外洩的金鑰讓你付一次代價;沒有上限的帳戶,每一天都在讓你付出代價。