什麼是中毒管道執行 (PPE)?
中毒管道執行 (Poisoned pipeline execution, PPE) 是 OWASP CI/CD 安全風險之一,是濫用原始碼管理 (SCM) 系統存取權限的攻擊媒介,目的是導致 CI 管道執行惡意指令。雖然 PPE 攻擊者無法存取建立環境,但他們已取得 SCM 的存取權,這使他們能夠將惡意程式碼注入建立管道組態,以操控建立程序。
CICD-SEC-4:中毒管道執行說明
中毒式管道執行 (Poisoned pipeline execution,PPE) 在 OWASP 的十大 CI/CD 安全風險中被列為 CICD-SEC-4,代表著針對持續整合與持續部署 (CI/CD) 系統的複雜攻擊策略。
客戶可能有多種選擇:
在 PPE 策略中,攻擊者會在 CI/CD 管道的 CI 部分中執行惡意程式碼,繞過直接存取 CI/CD 系統的需要。此方法涉及針對程式碼管理 (SCM) 儲存庫操作權限。透過變更 CI 設定檔案或 CI 管道作業所依賴的其他檔案,攻擊者可注入惡意指令,有效毒化 CI 管道,並使未經授權的程式碼得以執行。
成功的 PPE 攻擊可以實現廣泛的作業,所有作業都是在管道的身分範圍內執行。惡意作業可能包括存取 CI 作業可用的機密、存取作業節點有權限的外部資產、將看似合法的程式碼和工件運送至管道,以及存取作業節點網路或環境中的其他主機和資產。
鑑於其重要影響、低可偵測性,以及存在多種威脅偵測技術,PPE 攻擊構成了廣泛的威脅。對於安全性團隊、工程師和紅隊人員而言,瞭解 PPE 及其對策對 CI/CD 安全性至關重要
定義管道執行
在持續整合 (CI) 的情境中,管道執行流程是指由管道建置的儲存庫中託管的 CI 配置檔案所定義的作業順序。此檔案概述執行工作的順序,並詳細說明會影響流程的建立環境設定和條件。當觸發時,管道作業會從選取的來源 (例如 commit/分支) 抓取程式碼,並針對該程式碼執行 CI 配置檔中指定的指令。
管道中的指令可直接由 CI 配置檔案啟用,或間接由 CI 配置檔案中引用的獨立檔案中的腳本、程式碼測試或線程啟用。CI 設定檔案通常具有一致的名稱和格式,例如 Jenkinsfile (Jenkins)、.gitlab-ci.yml (GitLab)、.circleci/config.yml (CircleCI) 以及位於 .github/workflows 下的 GitHub Actions YAML 檔案。
攻擊者可以直接或間接利用管道執行指令的操控能力,在 CI 中執行惡意程式碼。
如何利用 CICD-SEC-4
要使 PPE 攻擊成功,必須符合幾項嚴重性標準:
- 攻擊者必須取得 SCM 儲存庫的權限。這可以是透過使用者憑證、存取權限、SSH 金鑰、OAuth 權限或其他方法。在某些情況下,匿名存取公共儲存庫可能就足夠了。
- 對相關儲存庫的變更必須觸發 CI 管道,而無需額外的核准或審查。這可能是透過直接推送到遠端分支,或是透過遠端分支或分叉的拉取請求所建議的變更。
- 攻擊者取得的權限必須允許觸發事件,導致執行管道。
- 攻擊者可以變更的檔案必須定義管道執行(直接或間接)的指令。
- 管道節點必須能存取非公開資源,例如機密、其他節點或計算資源。
執行未審核程式碼的管道,例如由拉取請求或提交至任意程式庫分支所引發的管道,較容易受到 PPE 的影響。一旦攻擊者可以在 CI 管道中執行惡意程式碼,他們就可以在管道的身分上下文中執行惡意作業。
三種中毒管道執行方式
中毒管道執行有三種不同的表現形式:直接 PPE (D-PPE)、間接 PPE (I-PPE) 及公共 PPE (3PE)。
直接 PPE
在直接 PPE 的情況下,攻擊者會修改他們可以存取的儲存庫中的 CI 設定檔,方法是直接將變更推送到儲存庫上未受保護的遠端分支,或是從分支或分叉提交包含變更的拉取請求。管道執行由推送或拉取請求事件觸發,由修改過的 CI 設定檔中的指令定義,一旦觸發建立管道,就會在建立節點中執行惡意指令。

圖 1:直接中毒管道執行攻擊流程
圖 1 所示的 D-PPE 攻擊範例依序經過以下步驟:
- 攻擊者在儲存庫中啟動一個新的遠端分支,以有害的指令變更管道組態檔案,以擷取儲存在 GitHub 組織中的 AWS 認證,並將其傳輸至攻擊者控制的外部伺服器。
- 程式碼推送會啟動一個管道,從程式碼儲存庫中拉取程式碼,包括惡意管道組態檔案。
- 管道根據配置檔案運作,現在已被攻擊者玷污。惡意指令會命令 AWS 認證(儲存為儲存庫機密)載入記憶體。
- 依照攻擊者的指示,管道會執行將 AWS 認證傳輸至攻擊者控制下的伺服器的任務。
- 竊取憑證後,攻擊者就有能力滲透生產環境。
間接 PPE
當敵人無法存取 SCM 儲存庫時,就會發生間接 PPE:
- 如果管道被設定為從同一套件庫中的另一個受保護分支拉取 CI 設定檔案。
- 如果 CI 設定檔儲存在與原始碼不同的程式碼儲存庫中,而使用者無法直接編輯。
- 如果 CI 建立是在 CI 系統本身中定義 - 而不是儲存在原始碼中的檔案。
在這些情況下,攻擊者仍可透過將惡意程式碼注入管道組態檔所引用的檔案,例如從管道組態檔內部引用的指令碼、程式碼測試,或 CI 中使用的自動工具 (如內嵌程式和安全掃描程式) 來毒害管道。例如:
- make 工具會執行 Makefile 檔案中定義的指令。
- 從管道配置檔內引用的程式碼,這些程式碼與原始碼本身儲存在相同的儲存庫 (例如:python myscript.py - 其中 myscript.py 將會被攻擊者操控)。
- 代碼測試:在建立過程中,在程式碼上執行的測試 Framework 依賴於專用檔案,與原始碼儲存在同一個程式碼儲存庫中。攻擊者若能操控負責測試的程式碼,就能在建立過程內執行惡意指令。
- 自動化工具:CI 中使用的 Linters 和安全掃描程式通常依賴駐留在程式碼儲存庫中的組態檔,該組態檔通常會從組態檔內定義的位置載入並執行外部程式碼。
發動間接 PPE 攻擊的攻擊者不是透過直接 PPE 來使管道中毒,而是將惡意程式碼注入組態檔案所引用的檔案中。惡意程式碼最終會在管道節點上執行,並執行檔案中宣告的指令。

圖 2:間接中毒管道執行攻擊流程
在這個 I-PPE 攻擊範例中,一連串的事件展開如下:
- 攻擊者在套件庫中建立拉取請求,將惡意指令附加到 Makefile 檔案。
- 由於管道已設定為在針對程式碼儲存庫的任何 PR 時觸發,因此 Jenkins 管道會被觸發,從程式碼儲存庫取得程式碼 - 包括惡意的 Makefile。
- 管道會根據儲存在主分支中的設定檔執行。它會進入建立階段,並將 AWS 認證載入原始 Jenkinsfile 中定義的環境變數。然後執行 make build 指令,執行加入 Makefile 的惡意指令。
- Makefile 中定義的惡意建立函式會被執行,將 AWS 認證傳送至攻擊者控制的伺服器。
- 攻擊者就可以使用竊取的憑證存取 AWS 生產環境。
公共個人防護裝備
Public PPE 是匿名攻擊者在網際網路上執行的一種 PPE 攻擊。公共儲存庫通常允許任何使用者貢獻,通常是透過建立拉取請求。如果公共程式碼儲存庫的 CI 管道執行匿名使用者建議的未審核程式碼,就很容易遭受公共 PPE 攻擊。在易受攻击的公共存储库的管道与私有存储库在相同的 CI 实例上运行的情况下,公共 PPE 还可能暴露内部资产,例如私有项目的机密。
CI/CD 中安全管道執行的重要性
透過成功的 PPE 攻擊在 CI 中執行未審查的惡意程式碼,可為攻擊者提供與建立工作相同等級的存取權限和能力:
- 存取 CI 作業可用的機密,例如注入為環境變數的機密或儲存於 CI 的其他機密。由於 CI/CD 系統負責建立程式碼和部署工件,因此通常包含數十個高價值憑證和令牌,例如到雲端提供商、到工件註冊處,以及到 SCM 本身的憑證和令牌。
- 存取工作節點有權限的外部資產,例如儲存於節點檔案系統中的檔案,或透過底層主機存取雲端環境的憑證。
- 能夠以建立程序所建立的合法程式碼為幌子,將程式碼和工件運送至更遠的管道。
- 能夠存取工作節點網路/環境中的其他主機和資產。
但 組織可以透過安全的管道執行來保護其軟體產品和基礎架構,確保所有編譯、測試和部署的程式碼都是合法且未被竄改的。
與中毒管道執行相關的風險
個人防護裝置可能會造成嚴重性的影響,從未經授權的資料存取、軟體完整性受損、系統中斷,到資料外洩,甚至完全接管系統。這些風險對企業及其客戶都構成重大威脅,突顯出個人防護裝備的重要性。

圖 3:中毒 CI 管道的下游影響
在圖 3 所示的八步供給鏈入侵作業中,攻擊者取得 CI 管道的存取權,並毒害 SaaS 應用程式的元件。透過中毒的元件,攻擊者會在應用程式中建立後門功能,並將中毒的外掛程式傳送至下游用戶端。由於下游組織可能認為中毒套件是合法的,因此他們會將其建構在雲端或內部部署基礎架構中。
從一個中毒的 CI 輸送管道,攻擊者就能創造出進入無數組織的後門存取,從而達到指數級的附帶損害。 SolarWinds 的攻擊就是這種情況。
閱讀更多: CI/CD 管道攻擊剖析
預防中毒管道執行
預防和減緩 PPE 攻擊向量涉及跨越 SCM 和 CI 系統的多重措施:
- 確保執行未審閱程式碼的管道是在隔離的節點上執行,而不是暴露在機密和敏感的環境中。
- 評估在外部貢獻者的公共儲存庫上觸發管道的需求。在可能的情況下,避免執行源自於 fork 的管道,並考慮加入控制措施,例如要求管道執行必須經過手動核准。
- 對於敏感的管道,例如暴露於機密的管道,請確保在 CI 系統中設定為觸發管道的每個分支,在 SCM 中都有相關性的分支保護規則。
- 為了防止竄改 CI 設定檔在管道中執行惡意程式碼,必須在管道執行前審查每個 CI 設定檔。另外,也可以在遠端分支中管理 CI 設定檔案,與包含管道中正在建立的程式碼的分支分開。遠端分支應設定為受保護。
- 移除不需要的使用者在 SCM 儲存庫上授予的權限。
- 每條管道都只能存取完成其目的所需的憑證。憑證應具有最低需求的權限。