Copy Fail: 透過頁面快取投毒破壞容器隔離

現代容器化環境的安全性依賴於一個假設:命名空間(namespaces)和 cgroups 能在工作負載之間提供強大的邊界。然而,最近披露的一個名為 "Copy Fail" 的漏洞打破了這個假設,其目標直指 Linux 核心的一個基本組件:頁面快取(page cache)。與依賴脆弱的競態條件(race conditions)或釋放後使用(Use-After-Free, UAF)漏洞來實現程式碼執行的傳統核心漏洞不同,Copy Fail 提供了一種確定性的原語(primitive),用於重寫快取的檔案內容,使攻擊者能夠在 Pod 之間進行橫向移動,甚至完全逃逸到主機。

Copy Fail 的機制

Copy Fail 的核心是一種本地權限提升漏洞,它利用了處理 IPSec ESP Extended Sequence Numbers (authencesn) 的核心程式碼中的記憶體損壞缺陷。此功能透過 AF_ALG socket 向非特權使用者開放,這是 Linux 核心加密子系統的使用者空間介面。

透過讓核心誤以為頁面快取的的可變引用(mutable reference)是可丟棄的暫存記憶體,攻擊者可以使用 splice(2) 對任何可讀檔案背後的頁面快取執行受控的 4 位元組寫入。這允許攻擊者在不改變實體磁碟上儲存的位元組的情況下,修改檔案的快取版本。由於該寫入繞過了標準的帳務處理(accounting)和 overlayfs 的 "copy-up" 機制,修改會直接發生在共享的底層檔案上。

為什麼容器容易受到攻擊

容器隔離是透過 mount、network、PID、user 和 IPC 命名空間來實現的。至關重要的是,這些命名空間中沒有一個會為每個容器建立獨立的頁面快取。核心的頁面快取是在整個系統中共享的。

在 Kubernetes 環境中,容器映像檔是由唯讀的底層層級(lower layers)組成的。為了節省空間,容器執行環境(如 containerdCRI-O)會根據內容雜湊值對這些層級進行去重(deduplicate)。如果同一個節點上的兩個不同 Pod 共享同一個基礎映像檔(例如 debian:bookworm-slimpython:3.12-slim),它們就會共享相同的底層主機 inode 和 address_space

當 Copy Fail 改變頁面快取中的一個 folio 時,所有指向該相同 address_space 的容器中的檔案描述符(file descriptor)都會看到修改後的位元組。這會產生兩個主要的攻擊向量:

場景 1:跨容器投毒

在此場景中,攻擊者若在一個 Pod 中擁有程式碼執行權限(或僅僅擁有建立 Pod 的權限),就可以針對廣泛共享的基礎層級進行攻擊。

  1. 目標選擇: 攻擊者識別一個常見檔案,例如 site-packages 中的 Python 模組或基礎層級中的 glibc 等共享函式庫。
  2. 寫入: 使用 Copy Fail,攻擊者串聯 4 位元組的寫入操作來修補頁面快取中的目標檔案。
  3. 觸發: 當同一個節點上的第二個不相關的 Pod 匯入該模組或執行該該函式庫時,它會從快取中載入被投毒的位元組並執行攻擊者的程式碼。

這使得攻擊者能夠僅僅因為一個加固過的後端 Pod 與同一個節點上受損或由攻擊者控制的 Pod 共享基礎映像檔,就能入侵該後端 Pod。此外,如果攻擊者擁有 pods/create 權限,他們可以刻意地將 Pod 調度到受害者的節點上,並拉取相同的基礎映像檔來觸發投毒。

場景 2:容器逃逸至主機 Root

Copy Fail 也可用於實現從非特權容器到主機的完全逃逸。此路徑反映了 "Dirty Pipe" 逃逸模式:

  1. 強制執行 runc 攻擊者在容器內使用指向 /proc/self/exe 的 shebang 來覆寫 /bin/sh。當管理員執行 kubectl exec 時,runc 會被調用並被固定在容器的 PID 命名空間中。
  2. 定位與投毒: 攻擊者識別 runc 程序並開啟其 /proc/<pid>/exe 符號連結。由於 runc 是從主機透過 bind-mount 掛載的,這提供了一個通往主機頁面快取中 runc 二進位檔的路徑。
  3. 執行: 攻擊者使用 Copy Fail 覆寫 runc 的 ELF header,其中包含惡意酬載。下次 runc 在主機上執行(透過探測、Pod 啟動或另一個 exec)時,惡意程式碼將以主機 root 權限執行。

檢測與緩解措施

Copy Fail 最危險的面向之一是其對傳統安全工具的不可見性。由於磁碟上的位元組保持不變,映像檔註冊表掃描器(Trivy、Clair)、無代理程式磁碟掃描器以及檔案完整性監控工具(AIDE、Tripwire)都會報告系統是乾淨的。

有效防禦措施

防禦機制 有效性 備註
Kernel Patching 唯一的永久修復方法是將主機核心更新至已修補的版本。
Seccomp Profiles 阻斷 socket(AF_ALG, ...) 可以移除該漏洞原語。
gVisor / Kata Containers 這些提供獨立的核心或 microVM,消除了共享頁面快取的問題。
Managed MicroVMs (Fargate) 每個 Pod 都有獨立的核心,可防止跨 Pod 投毒。
Runtime EDR 部分 可以檢測執行後的行為或記憶體中的頁面不匹配。

結論

Copy Fail 證明了 Linux 頁面快取的共享性質是容器安全中一個重大的架構盲點。雖然命名空間提供了資源的邏輯分離,但核心的記憶體管理仍然是一個全域資源。對於需要強多租戶環境的組織而言,此漏洞強化了論點:容器不應被視為主要的安全性邊界,且基於 VM 的隔離(或像 gVisor 這樣的沙盒執行環境)對於保護高風險工作負載至關重要。

Sources