跳到正文
DEV Community· Sam LABBE·· 1 小時前精選AI 評分77

Gheist 利用被盜 GitHub Token 在 13,500 個分支植入竊密工作流程,並提供 5 分鐘自查方法

Gheist: 13,500 secret-dumping workflows planted with stolen GitHub tokens — audit yours in 5 minutes

AI 導讀

Gheist 利用被盜 GitHub Token,在可觸及的儲存庫植入 13,500 個分支,加入傾印機密資料的工作流程。

推薦理由

文章把 Gheist 的分支特徵、GitHub 與 CloudTrail 查核方法,以及命中後的憑證處置串成一套自查流程,可用來檢視 CI 環境。

正文 · 繁體中文

當所有人都在關注 LiteLLM 時,一場較低調的攻擊行動花了五星期做出更嚴重的事:利用竊取的 GitHub 權杖,在所有可存取的儲存庫中提交一套用來傾倒機密的工作流程——在 850 多個遭入侵帳戶中植入了 13,500 個分支,包括個人專案及企業私有儲存庫。Wiz 昨日發表了完整剖析報告。這場行動名為 Gheist,會傾倒你組織的機密和雲端憑證,還會——這正是促使我寫下本文的原因——專門搜尋AI 服務供應商的金鑰:Anthropic、Hugging Face、Groq、NVIDIA。你各個 Agent 的金鑰,就這樣直接從 CI 中取走。

本文講解其運作機制及如何進行審查。使用 gh,今晚即可在自己的帳戶及組織中,於五分鐘內完成整項檢查。

攻擊分為四個步驟

Gheist 的工具會取得竊來的權杖(來源包括資訊竊取程式的日誌,以及以往的供應鏈事故——與 3 月攻擊 Trivy 的是同一類程式),列出所有可存取的儲存庫,並植入一個名為 ci-sync-XXXXXX 的分支,其中包含一個以 ci: sync config 提交、未經簽署的工作流程。這個工作流程只有兩行簡單指令:傾印 env 和 toJSON(secrets),再以base32 編碼後輸出到工作流程日誌。然後,工具透過 GitHub API 取回日誌,再刪除該次執行。

有四個細節令這種做法相當巧妙,值得全部記住:

  1. base32 可繞過機密遮罩。只有當機密值以原樣出現在日誌中時,GitHub 才會遮罩它們。將機密值編碼後,遮罩機制便偵測不到。你的 $SECRET 會毫無阻礙地輸出給攻擊者。
  2. permissions: {} 在這裏毫無保護作用。它限制的是自動產生的 GITHUB_TOKEN,而不是 secrets 內容。網上有一半的強化安全建議,針對的其實是另一種攻擊。
  3. 環境矩陣。工具 B 會列出儲存庫的部署環境,因此環境範圍限定的機密——通常屬於正式環境,也通常是最重要的核心資產——也會被輸出。
  4. 完全沒有 C2。機密是透過 GitHub 自己的 API 傳出,流量來自 GitHub 自己的 IP,並使用你簽發的權杖進行驗證。沒有可封鎖的攻擊者網域,也沒有可發出警報的資料外洩主機。傳輸通道就是平台本身。

在自架 Runner 上,攻擊載荷還會做更多事:搜尋 31 種權杖格式(私鑰、.env 檔案、Terraform 狀態、/proc/*/environ、Docker socket、Kubernetes 權杖),並專門搜尋 AI 服務供應商的金鑰。Wiz 指出,這個變體有不少錯誤——Runner 路徑錯誤、regex 故障、沒有收集 GCP/Azure 資料——但這反而更糟:這場行動就像一個仍在積極迭代、持續推出功能的產品。

公開與私有儲存庫的差異

這份剖析中最值得注意的一點是:一項不太起眼的 GitHub 防護措施,讓公開儲存庫大多得以倖免。自 7 月 28 日起,公開儲存庫中由首次貢獻者觸發的工作流程執行,會在 action_required 等候協作者批准;Wiz 檢查的每一次公開儲存庫 Gheist 執行都停在該狀態,攻擊載荷從未執行。

這項暫停不適用於私有儲存庫或 GitHub Enterprise Server。在這些地方,工作流程確實執行了,機密也遭到傾倒;Wiz 亦透過 CloudTrail 證實,攻擊者利用被竊的雲端憑證進一步切換至 AWS 角色。你從未自行設定的防護措施保護了你的開源專案;但沒有任何措施保護私有內容,而真正的機密就在那裏。

另外兩項值得一提的發現:攻擊者在惡意工作流程中使用了 permissions: {}——只是表面裝飾,畢竟機密資料不會在乎——而約三分之二涉事帳戶此後已從 GitHub 消失;這顯示應對工作可能已展開,但這場行動截至 10 月 24 日仍持續演變。

今晚花五分鐘進行審核

雷達提示:提交訊息可在公開歷史記錄中搜尋,但搜尋結果很多(到處都有合法的 sync config 提交),所以應把它當作尋找線索的工具,而非定論:

gh api 'search/commits?q="ci: sync config"' --jq '.total_count'
# → 321 hits right now. Most are innocent sync scripts. Your job is the branch check below.

真正的自我審核——檢查帳戶中植入的分支(逐一遍歷你的儲存庫,搜尋分支模式):

gh repo list --limit 200 --json nameWithOwner --jq '.[].nameWithOwner' | while read r; do
  gh api "repos/$r/branches" --paginate --jq '.[].name' 2>/dev/null | grep -E '^ci-sync-[0-9a-z]{6}$' && echo "  ↑ HIT in $r"
done

適用於機構(只限機構擁有者——個人帳戶無法使用審核記錄 API;網頁介面的安全記錄是個人帳戶的替代方案):

# Workflow runs deleted within a minute of completing — Gheist's cleanup signature
gh api 'orgs/YOURORG/audit-log?include=all&phrase=workflow_run' \
  --jq '.[] | select(.action=="workflow_run.deleted")'
# The tool's user agent
gh api 'orgs/YOURORG/audit-log?include=all' --jq '.[] | select(.user_agent=="gheist")'

還有即使沒有 GitHub 記錄也有效的雲端搜尋方法——Wiz 最出色的技巧:搜尋工作階段/主體包含 ci-sync- 的 OIDC 角色承擔(GitHub 的 OIDC 主體包含 ref,因此植入的分支名稱會出現在你的 CloudTrail 中):

aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRoleWithWebIdentity \
  --start-time 2026-09-15 --max-results 20 | grep -i 'ci-sync'

如有任何命中:輪換該儲存庫可能接觸到的所有機密——刪除執行記錄並不能收回已被傾出的資料——撤銷用來推送的權杖,並檢查權杖擁有者的電腦是否有資訊竊取程式,因為權杖就是從那裏取得的。

為下一次攻擊加強防護

根據 Wiz 的清單,按成本由低至高排列:要求環境範圍的機密須經審核者批准(消除環境矩陣);將 OIDC 信任政策限定為只適用於受保護分支(阻止 ci-sync-* 角色承擔);優先使用GitHub Apps 或細粒度、短效權杖,而非傳統 PAT(減少單一遭竊權杖可觸及的範圍);以臨時方式執行自我託管執行器,不使用 Docker socket,也不開放無限制的中繼資料存取(阻止攻擊者以主機作為跳板)。切勿批准在 action_required 中處於暫停狀態的 sync-check 執行作業——那正是陷阱的入口。

重點摘要

Gheist = 遭竊權杖 + 一個只有兩行的工作流程 + base32 + GitHub 作為 C2,規模達 13,500 個分支。公開儲存庫幸而受惠於首次貢獻者暫停機制;私人儲存庫則付出代價。審核只需五分鐘的 gh 和一次 CloudTrail 查詢——如果你在 CI 中執行 AI 代理程式,這場行動的目標清單上甚至直接列出你的供應商。今晚檢查。

資料來源:Wiz — Gheist:試圖大規模濫用遭竊 GitHub 權杖 · CISA KEV / 警示中心 · 透過 gh api 進行的提交搜尋審核(以上命令,已即時驗證)

來源:DEV Community · dev.to