這是一篇針對 GitLab 近期出現的遠端程式碼執行(Remote Code Execution, RCE)漏洞的技術分析。對於初入行的工程師來說,這是一個非常經典的案例,展示了底層 C 語言記憶體管理錯誤如何被串聯,最終導致高層應用程式被完全接管。
漏洞背景與核心成因
這次漏洞的核心不在於 GitLab 的 Ruby 程式碼,而是在於一個名為 Oj 的第三方套件。Oj 是一個用 Ruby 撰寫但底層大量使用 C 語言實作的 JSON 解析器,目的是為了追求極高的解析效能。
問題出在 Oj 處理 JSON 資料時,存在兩個嚴重的記憶體損毀漏洞。由於 GitLab 使用一個名為 ipynbdiff 的組件來渲染 Jupyter Notebook (.ipynb) 檔案的差異(Diff),而這個組件會將使用者上傳的 JSON 內容直接交給 Oj 解析,這就為攻擊者開啟了一道門。
攻擊路徑的技術拆解
攻擊者不需要管理員權限,只要能將程式碼推送到專案中的一般使用者即可發動攻擊。整個攻擊鏈分為三個階段:
第一階段:記憶體位址洩露(Information Leak)
攻擊者上傳一個精心構造的 Jupyter Notebook 檔案並查看其 Commit Diff。利用 Oj 的第一個漏洞,解析器在處理特定的物件鍵值(Object Key)時,會發生長度截斷錯誤,導致它將一個指向記憶體堆疊(Heap Pointer)的實際位址回傳,並由 GitLab 渲染在網頁上。這讓攻擊者知道了伺服器記憶體的佈局,進而定位到 libc(標準 C 函式庫)的位置。
第二階段:控制執行流(Control Flow Hijack)
利用 Oj 的第二個漏洞,攻擊者可以觸發堆疊溢位(Stack Overflow)。當解析 JSON 的巢狀深度超過 1,024 位元組的限制時,攻擊者可以覆蓋解析器的回呼函數(Callback)。
第三階段:執行惡意指令(Payload Execution)
結合前兩個步驟,攻擊者將回呼函數的目標指向 libc 中的 system() 函式。這樣一來,當 GitLab 的 Puma 工作進程(Worker Process)解析該惡意檔案時,就會直接在伺服器上執行攻擊者指定的系統指令。
影響範圍與實務風險
此漏洞允許攻擊者以 git 使用者的權限執行指令。在典型的 GitLab 安裝環境中,這意味著攻擊者可以存取原始碼、Rails 秘密金鑰(Secrets)、服務憑證以及 CI/CD 的相關數據。
值得注意的是,這個攻擊過程需要一些時間。攻擊者需要透過自動化探測來定位記憶體位址,在全新的環境中約需 5 到 10 分鐘,而在運行較久的環境中可能需要 1 到 2 小時。
維運上的陷阱與更新建議
這次事件中最令人擔憂的是 GitLab 的更新公告方式。GitLab 在 6 月 10 日的更新中修復了此問題(透過將 Oj 升級至 3.17.3),但將其列在一般 Bug 修復清單中,而非安全修復表(Security-fix table),且沒有提供 CVE 編號或 CVSS 評分。這導致許多依照安全公告進行風險評估的維運人員忽略了這次更新。
對於使用 Helm 或 Operator 部署 GitLab 的團隊,請務必檢查運行 Puma 的 Webservice 映像檔(Image)版本,而非僅檢查 Chart 版本。
受影響版本與修復方案
受影響範圍涵蓋 GitLab CE/EE 15.2.0 至 18.10.7、18.11.0 至 18.11.4 以及 19.0.0 至 19.0.1。
請立即升級至以下版本或更新版本: 18.10.8 18.11.5 19.0.2
如果您的版本低於 15.2,由於該版本已不在 GitLab 的安全維護週期內,將不會收到回溯修復(Backport),必須直接遷移至受支援的最新版本。
來源:thehackernews.com
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。