KeyFrame內部研究專用

Black Hat USA 2025 | Uncovering and Responding to the tj-actions Supply Chain Breach

Black Hat·4月1日週三·40 min英文

三句話摘要

2025年3月,TJ Actions change-files GitHub Action 遭供應鏈攻擊,23,000+ 個倉庫的 CI/CD 憑證被竊取的完整攻擊鏈解析。 --- GitHub Actions 的可變 tag 機制加上共享記憶體空間,讓供應鏈攻擊者能以一個 fork commit 靜默竊取數萬條 CI/CD 憑證;唯有將 action 固定到 commit SHA 並對 runner 建立出站網路基線,才能在攻擊發生的第一時間察覺異常。 1. Impostor Commit 是核心武器

重點整理

重點
  • 1

    1. Impostor Commit 是核心武器

  • 2

    攻擊者無需直接修改目標倉庫程式碼,只需在 fork 中建立惡意提交,再將原倉庫的 release tag(如 v4、v44)指向該提交即可。因為 GitHub API 允許標籤指向 fork 中的提交,這個「幽靈提交」不會出現在倉庫任何分支的 commit history 中,傳統審查工具完全看不見。

  • 3

    2. 記憶體 dump 是憑證竊取的手法

  • 4

    GitHub Actions 透過 runner.worker 進程將 secrets 注入到步驟中,而同一台虛擬機上的所有第三方 action 共享主機記憶體空間。memdum.py 直接找到 runner.worker 進程並 dump 其記憶體,再從 dump 中搜尋 GitHub 已知的 secrets 儲存格式字串。

  • 5

    3. 雙層 Base64 是反偵測技巧

  • 6

    GitHub 會自動在 build log 中遮蔽已知格式的 secrets,包含 Base64 編碼版本。但若對 secrets 進行「兩次」Base64 編碼,GitHub 的遮蔽機制便無法識別,導致 secrets 以明文形式出現在公開的 build log 中供攻擊者收割。

  • 7

    4. 基線驅動的網路監控是唯一有效偵測手段

  • 8

    Step Security 透過對同一 workflow 執行 2,000+ 次後建立的出站網路基線,在第一時間察覺到原本不存在於基線中的異常連線(gist.githubusercontent.com),才得以在 15 分鐘內確認事故並通報。傳統 EDR 和安全工具對此攻擊完全失效。

  • 9

    --

實用技巧與重點

乾貨
  • 數字與規模
  • 受影響公開倉庫:23,000+
  • 從收到 Slack 通知到建立 GitHub issue:15 分鐘
  • 攻擊者劫持標籤到被發現:約 3 小時
  • TJ actions 遭下架時間:2025-03-15 14:00 UTC
  • TJ actions 倉庫遭下架後恢復:2025-03-15 22:00 UTC(清理後)
  • review dog 被入侵持續時間:僅約 2 小時(2025-03-11)
  • 入侵確認:CVE 於次日發布,高嚴重性(High Severity)
  • 偵測用 workflow 基線建立次數:2,000+ 次執行
  • GitHub Actions Marketplace 上可用 action 數量:25,000+
  • 工具與平台
  • 偵測工具:Step Security Harden Runner(CI/CD 環境的 EDR)
  • 開源替代監控工具:Wazuh、Falco、Tetragon
  • 漏洞利用腳本:memdum.py(託管於公開 GitHub Gist)
  • 攻擊入口:spotbugs/sonarfindbugs(PR 漏洞) → spotbugs/spotbugs → review dog/action-setup → TJ actions/changed-files
  • 發布機構:CISA(美國網路安全暨基礎設施安全局)發布安全公告
  • 技術手法
  • Impostor commit:在 fork 建立惡意提交,更新原倉庫 mutable tag 指向它
  • 記憶體 dump:掃描進程列表,找到 runner.worker,開啟並 dump 其全部記憶體
  • 繞過 secrets 遮蔽:雙層 Base64 編碼(單層會被 GitHub 自動遮蔽)
  • 滲出方式:secrets 印至 stdout,出現在 build log(公開倉庫可直接讀取)
  • 偽裝手法:commit 偽裝成 renovate bot 的提交,exploit code 從高信譽域名 gist.githubusercontent.com 下載
  • 防禦建議(4 項)
  • 對 CI/CD runner 建立出站網路基線 + 異常偵測
  • 建立組織層級的 GitHub Actions 白名單
  • 將第三方 action 的引用固定到不可變的 commit SHA(而非 tag)
  • 預先制定 GitHub Action 遭入侵的事故應變計畫(含憑證輪換流程)
  • --

結論

結論

GitHub Actions 的可變 tag 機制加上共享記憶體空間,讓供應鏈攻擊者能以一個 fork commit 靜默竊取數萬條 CI/CD 憑證;唯有將 action 固定到 commit SHA 並對 runner 建立出站網路基線,才能在攻擊發生的第一時間察覺異常。

完整解析

詳細

2025 年 3 月 14 日星期五下午,Step Security 的自動偵測系統發出 Slack 告警。Vun Sharma 與 Ashish Kurmi 隨即展開調查,在 15 分鐘內確認:`tj-actions/changed-files` 這個 GitHub Action 已遭入侵,所有版本的 release tag 全部被指向同一個惡意提交。這個 action 被超過 23,000 個公開倉庫使用,受害者涵蓋 GitHub、Meta、Microsoft、Hugging Face 等大型組織,以及無數私有倉庫。隔天,一個高嚴重性 CVE 正式確認此事,CISA 隨後發布國家級安全公告,CI/CD 供應鏈攻擊正式從理論走入現實。

攻擊的核心技術是「幽靈提交(Impostor Commit)」。GitHub 的 release tag 預設是可變的(mutable),攻擊者只需擁有對目標倉庫的寫入權限,便可將現有的 tag(如 v4、v44)重新指向任意提交。更狡猾的是,惡意提交本身存在於 fork 倉庫中,並不出現在原倉庫的任何分支歷史中,形成一個「可讀取但不可追溯」的幽靈狀態。任何透過掃描倉庫 commit history 的安全工具都無法發現它。惡意 action 被執行後,會先下載 `memdum.py`(一個託管於公開 GitHub Gist 的 Python 腳本),此腳本掃描主機上所有運行中的進程,找到 `runner.worker`——這正是 GitHub 用來將 secrets 注入工作流程的進程——然後直接 dump 其整個記憶體空間。由於同一台虛擬機上的所有第三方 action 共享主機記憶體,這種手法可以取得該次 workflow run 中所有的 secrets,包含 AWS 存取金鑰、GitHub Token、資料庫密碼等。為了讓竊取到的憑證能在 build log 中顯示而不被 GitHub 自動遮蔽,攻擊者對 secrets 進行了兩次 Base64 編碼——GitHub 的遮蔽機制只能識別單層編碼,雙層編碼後的字串會以明文出現在公開的 build log 中,讓攻擊者得以輕鬆收割。

這起攻擊本身是一條精心設計的供應鏈:起點是 `spotbugs/sonarfindbugs` 倉庫中的 PR(Pull Request)漏洞,透過此漏洞竊取了一個 Personal Access Token,進而入侵 `spotbugs/spotbugs`,再取得另一個 PAT,最終入侵 `review-dog/action-setup`。review dog 的組織設計存在缺陷:任何貢獻者一旦 PR 被合併,即自動獲得組織的寫入權限,導致大量外部人員持有寫入權限。`tj-actions/changed-files` 的倉庫中有一個測試用 workflow 會執行 review dog action,當 review dog 被入侵後,它同樣使用 memdum.py 竊取了 tj-actions 維護者的 PAT token,攻擊者拿到此 token 後,便對 tj-actions 的所有 tag 進行重新指向,完成整個攻擊鏈。review dog 本身僅被入侵約 2 小時(2025 年 3 月 11 日),正是獨立安全研究員 Adnan Khan 透過事後分析 build log 中 tag 所指向的 commit 不在倉庫中,才逆向追溯出這條攻擊鏈。

偵測此事件的關鍵方法論是「基線驅動的異常偵測」:對同一個 workflow 執行超過 2,000 次,記錄每次的出站網路連線,建立正常行為基線。當 3 月 14 日出現對 `gist.githubusercontent.com` 的新連線時,系統立即觸發告警。Step Security 的 Harden Runner 產品實現了此功能,但演講者也指出,Wazuh、Falco、Tetragon 等開源工具同樣可以建立類似的監控機制。演講最後給出四項具體建議:為 CI/CD runner 建立網路基線並偵測異常;對組織可使用的 action 建立白名單;將第三方 action 的引用固定到不可變的 commit SHA 而非可移動的 tag;以及預先制定 action 遭入侵後的事故應變計畫,涵蓋如何快速識別受影響的 workflow run 並輪換洩漏的憑證。

---

關鍵時刻

Pipeline v2

帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。

事實查核

Pipeline v2

說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

更多「Web2 安全」的內容

SANS Stormcast Tuesday, August 25th, 2026: DOUBLECUP PNG; WebAudio Fingerprinting; Expired Domains; Android; Car
7 min
Web2 安全英文PODCAST8月25日

SANS Stormcast Tuesday, August 25th, 2026: DOUBLECUP PNG; WebAudio Fingerprinting; Expired Domains; Android; Car

SANS Stormcast

  • PNG 容器攻擊的簡易性設計:Double Cup 不依賴複雜的 Exif 或隱寫技術,只用 PNG 副檔名和檔頭來偽裝,核心是利用 findstr 指令的常見可用性讓執行變得無需額外工具。
  • Web Audio API 的隱密指紋識別:音訊於增益零的無聲狀態下播放,使用者完全無感,但錄製波形足以建立裝置特徵,在瀏覽器原生功能層面難以區分是反詐欺還是過度追蹤。
  • 域名過期引發的串聯漏洞:DMARC 報告端點使用過期域名是常見疏漏,允許攻擊者透過簡單的域名註冊取得他人的 SPF/DKIM 錯誤報告,進而收集目標系統配置情報。
Risky Bulletin: Expired credit cards can be used for malicious transactions
5 min
Web2 安全英文PODCAST8月24日

Risky Bulletin: Expired credit cards can be used for malicious transactions

Risky Business

  • 支付安全的非對稱風險:Visa卡利用未加密的卡片資料與NFC通訊,攻擊者可藉由中間人技術竄改過期日期進行交易,但MasterCard、美運卡與Discover的防護更完善,顯示不同發卡機構的安全架構存在明顯差異。
  • 國家級駭客活動的連鎖延伸:北韓Lazarus集團在2月單一事件已累積100名受害者,涵蓋大學、警察部門、媒體與醫療機構,伊朗駭客則針對基礎建設如電力系統發動破壞性攻擊,反映地緣政治在網路戰爭中的升溫。
  • AI加速漏洞生態的雙面刃:AI工具催生近2萬份漏洞概念驗證代碼發布,但同時也導致大量失效漏洞代碼氾濫,增加資安團隊甄別真實威脅的難度;Mayer Protocol遭攻擊事件中,駭客用AI鏈接六個無關的小漏洞完成盜竊170萬美元的攻擊。
SANS Stormcast Monday, August 24th, 2026: More Entra Powershell; Entra Vulnerability; GitLab Vuln (and PoC); GTA 6 Leak Malware
5 min
Web2 安全英文PODCAST8月24日

SANS Stormcast Monday, August 24th, 2026: More Entra Powershell; Entra Vulnerability; GitLab Vuln (and PoC); GTA 6 Leak Malware

SANS Stormcast

  • Microsoft EntraID 的遠端代碼執行漏洞已由微軟修補,初期報告顯示已遭利用但後來更正為未遭利用。這反映 Microsoft 在雲端軟體安全上的透明度提升,對漏洞採用與內部軟體相同的 CVE 編號和公告流程。
  • PowerShell 指令碼可用於驗證 MFA 部署完整性,特別是找出未啟用 MFA 的遺漏帳號。同時可以分析 EntraID 登入日誌中的異常行為,如風險係數評估和地理位置檢測,幫助組織快速識別可疑登入。
  • GitLab 的 GraphQL 代碼注入漏洞允許未認證攻擊者刪除或修改儲存庫,潛在導致供應鏈攻擊。已有公開概念驗證 (PoC) 存在,使用內部部署 GitLab 的組織必須立即修補。