返回

2026/11/10

Kyverno CVE-2026-124440:當政策引擎成為通往叢集管理員的繞道

在 Kyverno 1.19.1 中,僅能在單一命名空間撰寫政策的租戶即可取得叢集管理員權限。本文說明繞過手法,以及升級前應檢查的項目。

許多團隊使用 Kyverno 來隔離 Kubernetes 租戶。它會在 API 伺服器儲存物件之前,依政策檢查每個物件,也可以讓命名空間擁有者為自己的命名空間撰寫政策。2026 年 11 月 8 日公布的 CVE-2026-124440 顯示了這種授權委派可能如何失效。在 Kyverno 1.19.1 中,只能在自身命名空間建立政策的租戶,可以讓 Kyverno 在該命名空間之外執行動作,並一步步取得叢集管理員權限。

修正自 10 月 20 日起已隨 Kyverno 1.19.2 提供。跳過該版本的叢集至今仍有風險。本文說明問題出在哪裡、權限提升如何進行,以及您應在自己的叢集中檢查哪些項目。

重點摘要

  • CVE-2026-124440(GitHub 安全公告 GHSA-39w8-hv5g-f73w)影響 Kyverno 1.19.1,已在 1.19.2 修正。CVE 紀錄的評分為 CVSS 4.0 下 9.4 分、CVSS 3.1 下 9.9 分。
  • 攻擊者只需要在自身命名空間建立命名空間層級 Kyverno Policy 的權限。
  • 政策中的 apiCall 以 Kyverno 准入控制器的 ServiceAccount 身分執行,該帳戶可以讀取其他命名空間,並建立叢集範圍的准入 webhook。這條路徑最終可取得叢集管理員權限。
  • 安全公告未列出任何緩解措施。請升級至 1.19.2,接著檢視哪些人可以建立政策,以及目前存在哪些 webhook。
  • 在我們查閱的資料來源中,尚無實際遭利用的通報。

命名空間限制原本應有的作用

Kyverno 政策在評估請求時,可以從 Kubernetes API 取得資料。這項功能稱為 apiCall:規則指定一個 urlPath,Kyverno 呼叫 API 伺服器,再將結果帶入規則。呼叫使用的是 Kyverno 自己的 ServiceAccount,而不是撰寫政策者的權限。

對於由平台管理員撰寫、作用於整個叢集的 ClusterPolicy,這是預期中的行為。但對於可開放租戶撰寫的命名空間層級 Policy,這就是風險。先前的安全公告(GHSA-c5qq-7g2q-cpqp 與 GHSA-5qq8-67g6-4h2w)指出,命名空間層級的 Policy 可以透過 apiCall 讀取其他命名空間,或寫入叢集範圍的物件。2026 年 9 月 10 日發布的 Kyverno 1.19.1 加入了「命名空間限制」(namespace clamp):執行呼叫前,Kyverno 會檢查路徑是否仍在政策所屬的命名空間內。

檢查與實際動作在何處分歧

1.19.1 的限制機制檢查的並不是實際送出的字串。根據安全公告,它會先解碼 urlPath 中的百分比編碼,將結果正規化(解析 .. 區段),再於這份清理後的副本中檢查命名空間。然而,請求本身送出時使用的仍是原始、未經處理的路徑。

只要解碼成功,這種做法就沒有問題。但如果路徑含有格式錯誤的百分比跳脫字元,例如結尾查詢字串中單獨出現的 %,解碼就會失敗。此時 1.19.1 的程式碼會改為檢查仍處於編碼狀態的原始字串。API 伺服器則沒有這種退回機制,它會完整解碼路徑並路由請求。結果是,限制機制看到的是租戶自己的命名空間,而 API 伺服器看到的卻是經過編碼、可跳出該命名空間的 .. 區段,指向另一個命名空間或叢集範圍的集合。

安全公告強調,這是一整類輸入,而不是單一攻擊酬載。封鎖某個特定字串並無法解決問題。根本的修正方式是讓驗證與執行使用完全相同的路徑。

1.19.2 正是這麼做的。依我們對 1.19.2 原始碼的解讀,Kyverno 現在會為路徑建立單一的標準形式,拒絕無法標準化的路徑,以該形式檢查命名空間,並將同一形式送往 API 伺服器。同一版本中修正的另一個相關問題 CVE-2026-122310(GHSA-3xfv-vq8x-qhg4),利用的也是清理後的檢查與原始請求之間的落差,手法是將 ../ 區段藏在 # 或 ? 之後。它是另一個獨立的 CVE,有自己的紀錄。

權限提升鏈的各個步驟

回報者在 Kubernetes 1.31 上,以標準 Helm chart 和預設值安裝的 Kyverno 1.19.1 示範了這條攻擊鏈。

  1. 建立命名空間層級的 Policy。租戶唯一的權限是在自身命名空間中建立 policies.kyverno.io。該政策包含一個 apiCall,其路徑能通過限制檢查,實際上卻被路由到其他地方。
  2. 觸發政策。只要建立任何符合該政策的一般物件,例如租戶命名空間中的 ConfigMap,Kyverno 就會評估規則,並以其准入控制器 ServiceAccount 的身分執行呼叫。
  3. 跨命名空間讀取。同樣的手法可以讀取其他命名空間中的物件;若 Kyverno 部署具有讀取權限,還包括 Secrets。
  4. 寫入叢集範圍的 webhook。該 ServiceAccount 可以建立 MutatingWebhookConfigurations 與 ValidatingWebhookConfigurations,因此租戶可以註冊自己的 webhook,進而攔截並改寫所有命名空間中的准入請求。
  5. 取得叢集管理員權限。安全公告描述了如何利用這樣的 webhook 修改在 kube-system 中建立的 pod,再由此授予租戶 cluster-admin 權限。結果是機密性、完整性與可用性全面喪失。

整個過程不需要任何使用者互動,而且 webhook 會在叢集的正常運作中被觸發。

受影響的對象

CVE 紀錄將 Kyverno 1.19.1 列為受影響版本,1.19.2 則列為不受影響。1.19.1 之前的版本沒有這個特定的繞過問題,因為它們根本沒有限制機制。不過,這些版本會受到該限制機制原本要修正的先前安全公告所影響,因此停留在舊版並不是安全的替代方案。在允許命名空間擁有者、CI 管線或自助服務入口網站建立 Kyverno Policy 的環境中,風險最高。

Kyverno 1.19.2 於 2026 年 10 月 20 日發布,其版本說明列出了 24 則 GitHub 安全公告:9 則嚴重、14 則高風險、1 則中度。其中有數則與 API 路徑驗證及命名空間隔離有關。本安全公告於三天後的 10 月 23 日公布,但安全公告與 CVE 紀錄都將 1.19.2 列為修正版本。每則安全公告都有各自的識別碼,因此請逐一比對,而不要把這一批公告當成單一 CVE 處理。

在您的叢集中應檢查的項目

首先,確認實際執行中的 Kyverno 版本,而不是 Git 儲存庫中記載的版本:

kubectl get deployments -n kyverno -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[*].image}{"\n"}{end}'

如果任何映像標籤為 v1.19.1,請立即規劃升級至 1.19.2。接著檢查以下四點:

  • 誰可以建立命名空間層級的 Policy。直接以租戶身分進行測試,並找出授予 policies.kyverno.io 的角色,包括會將權限加入內建 admin 與 edit 角色的聚合 ClusterRole。
  • 使用 apiCall 的既有政策。列出這些政策並檢視每個 urlPath,特別是含有 %、..、? 或 # 的路徑。
  • Webhook 設定。將清單與預期內容進行比對。Kyverno 會建立自己的 webhook,因此請著重於無法辨識的名稱及近期的建立時間。
  • 稽核日誌。找出由 Kyverno 准入控制器 ServiceAccount 發出、建立 webhook 設定或以異於平常模式讀取 Secrets 的請求。
kubectl auth can-i create policies.kyverno.io -n team-a --as=system:serviceaccount:team-a:default
kubectl get policies.kyverno.io -A -o json | jq -r '.items[] | select([.spec.rules[]?.context[]? | select(.apiCall)] | length > 0) | "\(.metadata.namespace)/\(.metadata.name)"'
kubectl get mutatingwebhookconfigurations,validatingwebhookconfigurations -o custom-columns=NAME:.metadata.name,CREATED:.metadata.creationTimestamp

請將 team-a 替換為您自己的租戶命名空間與身分。若在曾執行 1.19.1 的叢集上發現無法解釋的 webhook,請將其視為可能的資安事件:在移除任何東西之前,先保存稽核日誌。

更廣泛的教訓:稽核執行者本身

准入控制器、政策引擎與 operator 往往是叢集中權限最高的元件。它們需要廣泛的權限才能運作,而租戶每天都會與它們互動,這使它們成為誘人的攻擊目標。在這個案例中,租戶隔離模型仰賴單一檢查,而只要檢查與請求對同一個解碼步驟的處理方式不同,就足以將其攻破。

對於私有雲與多租戶 Kubernetes 平台,有三個習慣值得養成。將政策引擎視為攻擊面的一部分,並像追蹤 Kubernetes 版本一樣密切追蹤其安全性更新。只授予其 ServiceAccount 必要的權限,例如除非有政策需要,否則不授予讀取 Secret 的權限。此外,請檢視租戶可透過授權委派使用哪些功能,因為以平台權限執行的功能,會把租戶的輸入變成平台的動作。

資料來源