dPhhAt3dkwNe57E0VIETCopNBAvS4qtY0z2O1th0
Bookmark

《公開 Repo 密鑰外洩清除實錄》之一:.gitignore 的盲區與活密鑰偵測

這是一部關於開發者 Icekimo 與 AI 助理 Claude Fable 在 Debian 開發機 katharine 上,發現自己在 GitHub 公開 repo 洩漏敏感密鑰後,展開的一場驚心動魄的密鑰獵殺與歷史重寫實錄。


Icekimo

糟糕!我在 Synology NAS 上部署服務時,執行 `git status` 竟然看到了 `M .env`,但這檔案明明已經寫在 `.gitignore` 裡了。這是怎麼回事?

15:00
Claude Fable

這是一個非常經典且危險的 Git 陷阱。`.gitignore` 的機制是「只擋未追蹤的檔案」。如果一個檔案在被加入忽略名單前就已經被 commit 追蹤,那日後就算補上忽略名單,Git 依然會持續監控並追蹤它的修改。這意味著你的敏感資訊極有可能已經進了 GitHub!

15:02

敏感檔案追蹤檢測

聽完 Claude Fable 的分析,Icekimo 驚覺不妙,立刻在開發機終端機輸入指令,掃描整個專案到底有多少敏感檔案被偷偷追蹤了:

$ git ls-files | grep -iE 'credential|secret|\.env|password|token|key'
.env
crowdsec_config/local_api_credentials.yaml

「居然連 CrowdSec 的 LAPI 憑證也進去了...」Icekimo 倒吸一口氣。此時,Claude Fable 提議立刻再掃描一次目錄,以防還有漏網之魚。

$ ls crowdsec_config/
local_api_credentials.yaml
online_api_credentials.yaml

果不其然,第三個沒人記得的敏感檔案 online_api_credentials.yaml 靜靜地躺在目錄裡。

確認 Repo 是否對外公開

為了確認災情,Icekimo 必須驗證這個 GitHub Repo 是否已被公開。他使用了一個不需要帶 Token 的 GitHub API curl 指令:

$ curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/August-Icekimo/secure-gateway
200

「回傳 200... 專案真的是公開的。」Icekimo 感覺背後一陣涼風吹過,感凌涼啊。

評估洩漏嚴重性:值是「活的」還是「死的」?

Icekimo

既然已經公開了,那這些被推上去的密鑰現在是活的嗎?要怎麼比對而不把值印在終端機上(以防二次洩漏)?

15:05
Claude Fable

我們可以利用 `git show` 從 commit 歷史中抓出舊值,並透過 SSH 抓取 NAS 上生產環境的現用值直接進行字串比對,只輸出比對結果,不印出密鑰本身。

15:07

Icekimo 照著寫了一段比對指令:

# 比對 CrowdSec bouncer key
$ repo_key=$(git show HEAD:.env | grep CROWDSEC_BOUNCER_KEY | cut -d= -f2)
$ live_key=$(ssh nas 'grep CROWDSEC_BOUNCER_KEY /volume1/docker/secure-gateway/.env' | cut -d= -f2)
$ [ "$repo_key" = "$live_key" ] && echo "MATCH: 洩漏是活的" || echo "不同:是輪替過的舊值"

依此類推,他們將三個檔案進行了全面檢測,整理出以下令人堪憂的狀態表:

檔案 洩漏內容 狀態
.env 舊 bouncer key(其餘為 placeholder) 死的(已輪替過)
local_api_credentials.yaml 舊 LAPI 密碼 死的
online_api_credentials.yaml CrowdSec CAPI 帳密 活的 ⚠️ 與 NAS 現值完全相同

「最關鍵的 CrowdSec 中央 API 帳密居然是現役的的!」Icekimo 握著滑鼠的手不禁微微顫抖,難道是這隻mouse有通靈體質?

第一階段的偵測宣告結束,公開倉庫中躺著隨時可被利用的現役帳密,這場安全漏洞的即刻救援,必須在服務零中斷的前提下立刻展開。

導讀
選擇語音
1x
* 更改設定將重新朗讀文章。