文章总结: 本文是BlackHatUSA2026议题笔记,分析Kubernetes多租户隔离反复失效的根因:namespace仅是名称作用域而非安全边界,租户可通过跨namespace引用对象字段或annotation操控共享controller,形成confuseddeputy攻击。案例涵盖Kubeflow、Traefik和Istio,指出networkpolicy无法约束代理编程权,建议采用ReferenceGrant显式授权、关闭跨namespace引用并建立controllerannotation清单。
综合评分: 88
文章分类: 云安全,漏洞分析,安全建设,容器安全,安全工具
Black Hat USA 2026:K8s多租户隔离失效
原创
Max Luo
Max Luo
白帽子罗棋琛
2026年9月19日 12:59
广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
Kubernetes 多租户隔离为何反复失效
Black Hat USA 2026 议题笔记:Breaking Multi-Tenancy Over and Over, and What We Can Learn From This
很多平台团队没有把集群称为“多租户”,却允许不同研发团队、客户 Notebook、CI Job、模型训练任务、Webhook、脚本或第三方 Controller 在同一 Kubernetes 集群中运行。只要这些 Actor 的信任等级不同,共享集群就已经形成多租户环境。
常规加固通常围绕 RBAC、NetworkPolicy、Pod Security Standards、Admission Controller、镜像扫描和 ResourceQuota 展开。这些措施都必要,但无法自动保证 Namespace 隔离。原因在于 Kubernetes 生态中大量 Namespaced Resource 会被高权限 Controller 解释,并影响其他 Namespace、共享入口、整个 Service Mesh,甚至集群外部系统。
Lorin Lehawany 与 Sven Nobis 的公开课件用 Kubeflow、Traefik 和 Istio 三组案例说明了同一类设计缺陷:租户只能创建自己 Namespace 中的对象,却能在对象字段或 Annotation 中引用其他租户资源。Controller 以更高权限解析引用并更新全局配置,原本正确的 RBAC 因而变成 Confused Deputy 的入口。
图 1:材料研究 Namespace-based Multi-Tenancy 在控制平面和数据平面上的反复失效
1、Namespace 是名称作用域,不是天然安全边界
Kubernetes Namespace 提供名称隔离、RBAC 作用域、配额和策略挂载位置,但它没有承诺所有 Namespaced Object 只影响本 Namespace。一个 VirtualService 可以重写共享 Gateway 或 Mesh 的路由;一个带 Annotation 的 Service 可以要求 Ingress Controller 使用其他 Namespace 的 TLS Transport;一个自定义资源可以让 Operator 在另一个 Namespace 创建工作负载。
图 2:租户对象位于不同 Namespace,Controller 和数据面却可能由整个集群共享
判断隔离不能只问“租户能否读取别人的 Secret”,还应检查四种影响:
text
控制平面:租户对象能否改变其他 Namespace 中 Controller 的行为? 数据平面:租户规则能否重定向、截获或阻断其他工作负载流量? 身份平面:租户能否让共享组件代表更高权限身份执行? 集群外部:租户引用能否影响云证书、负载均衡器、DNS 或外部密钥?
Namespace-based Multi-Tenancy 更准确的名称应是 Soft Multi-Tenancy。若租户包含互不信任的客户、可执行任意代码的 Notebook 或外部贡献者,默认假设应是“共享 Controller 的任何可配置字段都可能跨边界”。
2、不明显的多租户比显式 SaaS 更危险
课件列出机器学习、数据摄取、Webhook、带脚本能力的复杂应用、CI/CD、AI Agent 和第三方 Controller。这些系统常常给用户“间接创建资源”的能力:用户在 UI 中提交模型或 Pipeline,后台再生成 Pod、Service、VirtualService 和 ServiceAccount。
图 3:即使团队未主动设计多租户,只要不同 Actor 共享控制面就已经存在租户边界
资产盘点应把“谁可以影响对象”与“谁拥有 Kubernetes Verb”分开。下面的清单可作为 Cluster Review 输入:
yaml
tenant:id:customer-notebooktrust:untrustedentry_points:-kubeflow-notebook-ui-pipeline-uploadidentities:-system:serviceaccount:tenant-a:default-editordirect_resources:-pods-services-configmaps-virtualservices.networking.istio.ioindirect_resources:-ingress-gateway-routes-kserve-inferenceservices-service-mesh-xdsshared_controllers:-istiod-kubeflow-profiles-controller-kserve-controllersecurity_boundary_expected:namespaceadversary_can_run_arbitrary_code:true
indirect_resources 才是多租户审计的重点。一个租户 ServiceAccount 可能没有 get secrets -n victim,但它创建的对象会让 Controller 读取 Secret 或让 Gateway 使用其中的证书。RBAC 报表不显示这条间接能力。
3、跨 Namespace 引用制造 Confused Deputy
课件用两个抽象 CRD 展示问题:ns2 中的 SourceCRD 在字段里引用 ns1 的 TargetCRD。Kubernetes API Server 只检查提交者能否在 ns2 创建 SourceCRD,通常不会理解引用的安全语义。
图 4:引用是普通字段,API Server 不会自动验证调用者是否有权使用目标对象
随后,Controller 以 ClusterRole 读取 ns1 的目标并执行配置。于是权限判断出现断层:
text
用户权限:可以在 ns2 创建 SourceCRD Controller 权限:可以读取所有 Namespace 的 TargetCRD 缺失检查:用户是否有权把 ns1/TargetCRD 绑定到自己的对象
安全引用至少需要以下约束:
- 默认只允许同 Namespace;
- 跨 Namespace 必须由目标 Namespace 显式授权;
- 授权要绑定 Group、Kind、来源 Namespace 和可选对象名;
- Controller 在 Reconcile 时再次验证授权,不能只依赖 Admission;
- 删除授权后,已有绑定要失效或进入明确的降级状态;
- Status 中记录解析到的目标 UID,防止删除重建导致引用漂移。
Gateway API 的 ReferenceGrant 正是这种双向同意模型:来源创建引用,目标 Namespace 明确允许哪类来源使用哪类对象。
yaml
apiVersion:gateway.networking.k8s.io/v1beta1kind:ReferenceGrantmetadata:name:allow-team-a-certificatenamespace:gateway-systemspec:from:-group:gateway.networking.k8s.iokind:HTTPRoutenamespace:team-ato:-group:""kind:Secretname:team-a-public-cert
ReferenceGrant 不应写成允许任意 Namespace、任意 Secret 的全局通行证,否则只是把隐式风险改成显式风险。
4、Kubeflow:租户路由如何借用共享 Gateway
课件中的 Kubeflow 场景允许 Notebook 的 default-editor ServiceAccount 创建 Istio 资源。攻击者在自己的 Namespace 创建 VirtualService,却把 gateways 指向 kubeflow/kf-gateway。
图 5:攻击对象属于 attacker Namespace,但它绑定的是 kubeflow Namespace 的共享入口
如果 Gateway 的 Host 范围过宽,租户就能把特定路径路由到自己的 Pod,截获进入共享域名的 Cookie 或请求。材料继续展示了更严重的组合:借共享入口访问原本受 NetworkPolicy 隔离的内部 Web Application,设置其信任的用户标头,再诱导高权限 Controller 创建资源。
图 6:共享 Gateway 把外部请求导向攻击者 Pod,Cookie 与应用会话成为跨租户资产
图 7:NetworkPolicy 允许 Gateway 到后端的合法流量,却无法判断路由由哪个租户创建
这里的关键不是复现 Exploit Manifest,而是理解权限复合:
yaml
effective_capability:tenant_can_create:-VirtualService/in-own-namespaceshared_controller_can_configure:-gateway-routes/across-namespacesgateway_can_reach:-internal-kubeflow-servicesbackend_trusts:-identity-header-from-gatewaydownstream_controller_can_create:-workload-with-selected-service-account
任何一层单独看都可能“符合设计”,组合后却形成垂直提权。课件称 CVE-2026-47237 的修复包括移除 ServiceAccount 的 Istio Edit 权限,并引入 Multi-domain Setup 处理钓鱼场景。研究者公开披露也给出了相同时间线;由于 CVE 数据库记录一度仍为 Reserved,生产判断应以 Kubeflow 实际发布版本、Manifest Diff 和项目公告为准,而不是只看扫描器是否识别编号。
图 8:删除默认 Editor 的 Istio 权限能切断当前链,但跨 Namespace 引用仍是通用设计问题
5、NetworkPolicy 不会约束“谁编程了代理”
NetworkPolicy 处理 Pod 间 L3/L4 连接,部分实现支持更多能力,但它不理解 Istio VirtualService 的所有权。若共享 Ingress Gateway 被允许访问内部服务,任何能修改 Gateway Route 的租户都可能借用这条合法网络路径。
这与 SSRF 的结构相似:攻击者不能直接连接目标,却能控制一个已获准访问目标的中介。区别是中介不是某个 HTTP Fetcher,而是整个 Ingress 或 Service Mesh 控制面。
防御必须同时约束两个问题:
text
Connectivity:Gateway 是否可以访问目标? Delegation:谁可以要求 Gateway 把哪类请求发给目标?
可以用 Istio Gateway 的 Host Namespace 语法限制允许绑定的 VirtualService 来源,而不是配置全局 *:
yaml
apiVersion:networking.istio.io/v1kind:Gatewaymetadata:name:team-a-gatewaynamespace:gateway-systemspec:selector:istio:ingressgatewayservers:-port:number:443name:httpsprotocol:HTTPShosts:-"team-a/app.team-a.example.com"tls:mode:SIMPLEcredentialName:team-a-cert
敏感系统还应使用独立 Gateway Deployment 与 ServiceAccount,避免所有租户共享同一个高连通性代理。授权标头必须由 Gateway 在认证后覆盖并签名,后端不能接受客户端或租户路由配置直接设置的身份标头。
6、Annotation 是没有 Schema 的控制面 API
第二组案例来自 Traefik。Kubernetes Service Annotation 可以指定 ServersTransport;后者又能引用客户端证书 Secret,控制 Traefik 到上游服务的 mTLS 行为。若允许跨 Namespace 引用,攻击者可在自己的 Service 上引用 Victim Namespace 的 Transport,让共享 Traefik 使用受害者证书建立连接。
图 9:Annotation 看似只是字符串,Controller 却把它解释为跨资源引用
图 10:Controller 读取 Victim 的证书配置,并替攻击者流量完成 mTLS
这类问题比 CRD Field 更难治理:Annotation 没有 OpenAPI Schema,拼写、格式和目标 Kind 完全由 Controller 自行解释。平台团队应建立 Controller Annotation Inventory:
yaml
annotation_contract:key:traefik.ingress.kubernetes.io/service.serverstransportcontroller:traefiksource_kinds:-core/v1/Servicereference_target:group:traefik.iokind:ServersTransportcross_namespace:deniedtarget_may_reference_secrets:trueadmission_policy:deny-cross-namespace-serverstransportowner:platform-networking
Traefik 当前文档写明,跨 Namespace 引用格式为 namespace-name@kubernetescrd,并且 Provider 必须启用 allowCrossNamespace。多租户集群应保持该选项关闭,逐步迁移到带显式授权模型的 Gateway API;还要扫描现有对象,因为关闭新建并不会自动删除历史引用。
7、Service Mesh 的 Namespaced CRD 可能具有全 Mesh 语义
第三组案例不再依赖共享 Ingress。Istio VirtualService 使用 gateways: [mesh] 时,可以控制 Sidecar 出站到某个 Host 的流量。拥有自己 Namespace 中 VirtualService 权限的租户,可能为其他 Namespace 正在访问的外部 Host 创建路由,将请求重定向到攻击者服务。
图 11:Namespaced VirtualService 的 Host 规则可影响 Mesh 中其他工作负载的出站流量
Istio 官方 ISTIO-SECURITY-2026-002 将其描述为 Namespace-based Multi-Tenant 环境中的 Man-in-the-Middle 场景:攻击者需要在某 Namespace 创建 VirtualService 的高权限,但可重定向 Mesh 中其他 Pod 的流量。官方同时说明,它不能绕过目标侧已经配置的 Istio AuthorizationPolicy 或 mTLS;问题来自历史 CRD 的全 Mesh 流量管理语义,并被视为有意的用户体验取舍。
图 12:该行为影响自 mesh Gateway 选项引入后的版本,官方建议多租户场景迁移 Gateway API
缓解不能只写一个版本号,因为官方没有把它定义为可通过常规补丁消除的实现 Bug。可选措施包括:
- 不向非可信租户授予 Istio 流量管理 CRD 写权限;
- 使用 Gateway API 替代传统 VirtualService 委派;
- 按租户拆分 Cluster、Mesh 或 Istio Control Plane;
- 使用
discoverySelectors限定各控制面观察的 Namespace; - 对
hosts、gateways、exportTo和 Destination 做 Admission Allowlist; - 为敏感服务部署 mTLS 与 AuthorizationPolicy,不能只依赖路由正确;
- 通过 Egress Gateway 和 DNS/Host 策略收敛外部流量。
exportTo: ["."] 可以减少资源向其他 Namespace 可见,但它必须结合版本、资源类型和路由合并语义测试,不能当作通用隔离开关。
8、用“Use、Assess、Address”审计租户能力
课件给出三阶段方法:确认是否存在 Namespace-based Multi-Tenancy,评估租户控制的组件和交互,再通过厂商修复、现有 Policy Set 或自定义策略处理。
图 13:先应用基线加固,再识别租户控制的资源及其控制面、数据面影响
评估可以从 Kubernetes Discovery 和 RBAC 开始,但必须继续追踪 Controller:
python
from dataclasses import dataclass @dataclass(frozen=True)classResourceCapability: group: str kind: str namespaced: bool tenant_can_write: bool controller_scope: str supports_cross_namespace_ref: bool affects_data_plane: bool references_secrets: booldefhigh_risk(capability: ResourceCapability) -> bool: ifnot capability.tenant_can_write: returnFalsereturnany([ capability.controller_scope == "cluster", capability.supports_cross_namespace_ref, capability.affects_data_plane, capability.references_secrets, ]) defreview_reason(capability: ResourceCapability) -> list[str]: reasons = [] if capability.controller_scope == "cluster": reasons.append("cluster-scoped reconciler") if capability.supports_cross_namespace_ref: reasons.append("cross-namespace reference") if capability.affects_data_plane: reasons.append("changes shared traffic") if capability.references_secrets: reasons.append("indirect secret use") return reasons
这份模型要由平台工程师补充语义,不能指望 API Discovery 自动判断 affects_data_plane。最有效的资料通常是 Controller 源码中的 Informer Scope、Reconcile 查询、Reference Parser、所用 ClusterRole 和最终写入的代理配置。
9、Admission Policy 要验证引用关系,不只验证资源本身
课件建议用 Admission Control 限制 VirtualService 的 Gateway 与 Host。对非可信租户,默认拒绝 mesh、带 / 的跨 Namespace Gateway、通配 Host 和非批准 Service Destination。
图 14:策略需要同时检查 Gateway 引用和 Host 影响范围
下面是一条 Gatekeeper Rego 骨架,按 Namespace Label 中的平台授权限制 Istio VirtualService。实际部署前应结合对象 Schema 和团队域名规则补齐测试:
rego
package kubernetes.admission.istio_tenancy violation contains {"msg": msg} if { input.review.kind.group == "networking.istio.io" input.review.kind.kind == "VirtualService" tenant_namespace some gateway in input.review.object.spec.gateways gateway == "mesh" msg := "tenant VirtualService must not attach to the mesh gateway" } violation contains {"msg": msg} if { input.review.kind.group == "networking.istio.io" input.review.kind.kind == "VirtualService" tenant_namespace some gateway in input.review.object.spec.gateways contains(gateway, "/") msg := sprintf("cross-namespace gateway reference denied: %s", [gateway]) } violation contains {"msg": msg} if { input.review.kind.group == "networking.istio.io" input.review.kind.kind == "VirtualService" tenant_namespace some host in input.review.object.spec.hosts host == "*" msg := "wildcard VirtualService host denied in tenant namespace" } tenant_namespace if { input.review.namespace_labels["platform.example/trust"] == "tenant" }
策略需要覆盖 Create 与 Update,也要审计已有对象。Controller 升级、新 CRD Version 和 Annotation Key 变化时应重新生成测试语料。最好采用“允许的引用”白名单,而不是不断添加已知危险字符串。
可以用无害的负向测试验证策略:
yaml
apiVersion:networking.istio.io/v1kind:VirtualServicemetadata:name:policy-negative-testnamespace:tenant-testspec:hosts:-"*"gateways:-meshhttp:-route:-destination:host:harmless.tenant-test.svc.cluster.local
验收结果应是 API Server 拒绝该对象,并在 Audit Log 中记录具体 Policy,而不是对象创建后由 Controller 忽略。
10、强租户隔离最终要减少共享权力
Namespace Policy 可以显著提高 Soft Multi-Tenancy,但无法把共享 API Server、Node Kernel、CNI、CSI、Ingress、Mesh Control Plane 和高权限 Operator 变成真正独立的信任域。租户越不可信,越应该把隔离单位上移到 Virtual Cluster、独立 Cluster、独立 Mesh 或独立云账号。
迁移优先级可以按影响与共享程度排序:
yaml
isolation_tiers:trusted_internal_teams:boundary:namespacerequirements:-reviewed_rbac-network_policy_default_deny-admission_cross_namespace_deny-shared_controller_inventorysemi_trusted_workloads:boundary:virtual_cluster_or_dedicated_node_poolrequirements:-separate_ingress-separate_service_accounts-restricted_crds-sandboxed_runtimeuntrusted_customers:boundary:dedicated_clusterrequirements:-separate_control_plane-separate_mesh-separate_cloud_identity-explicit_cross_cluster_gateway
图 15:Namespaced Resource 的影响可能落到控制面、数据面,甚至越出集群边界
这场研究给平台工程最直接的提醒是:不要用 metadata.namespace 推断安全作用域。真正的作用域由 Controller 读取什么、以谁的身份读取、把结果写到哪里以及数据面如何消费共同决定。
每增加一个 Operator、Ingress Controller、Service Mesh 或 ML 平台,都应问三个问题:租户能控制哪些对象?这些对象引用了什么?共享组件最终替租户做了什么?只要第三个答案超出 Namespace,就需要双向授权、Admission Policy 或更强的物理隔离。
延伸资料:Istio ISTIO-SECURITY-2026-002 · Istio 多租户安全模型 · Traefik ServersTransport 跨 Namespace 配置
Black Hat 官方 Session 页面
原始会议材料(仓库内)
- 演讲课件 PDF
开源资料与原始议题 PDF
本文对应的 Markdown 原稿、Black Hat 原始议题 PDF 与配图已整理到 GitHub,可按文章编号查找和下载。
https://github.com/cybermaxluo/black-hat-usa-2026-talks
也可以点击文末“阅读原文”进入仓库。欢迎 Star、提交 Issue 或参与勘误。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:白帽子罗棋琛 Max Luo
Max Luo《Black Hat USA 2026:K8s多租户隔离失效》