0x00 前言
最近逛知识星球的时候发现 Spring Cloud GateWay 出现了一个 SPEL 漏洞,所以就从官方的 Github Commit & 官方文档来跟进一下
0x01 影响版本
Spring Cloud GateWay
- 3.1.0
- < = 3.0.0 - 3.0.6
0x01 分析
官方的漏洞通告地址:https://spring.io/blog/2022/03/01/spring-cloud-gateway-cve-reports-published
可以看到有两个漏洞,没关系我们只关注 RCE,描述中看到 Spring Cloud 的影响版本如下
直接去到 Github 查看 commit 记录,可以很快定位到漏洞修补代码
https://github.com/spring-cloud/spring-cloud-gateway/commit/818fdb653e41cc582e662e085486311b46aa779b
下载源码 3.1 的代码可以直接定位到漏洞处,ShortcutConfigurable#getValue
可以看到如果 rawValue 如果是 #{ 开头同时 } 结尾,就会进入到 SPEL 解析的部分
找到了漏洞点之后我们只需要向上查找调用就可以了,发现在当前文件的 ShortcutType 中调用了 getValue 获取值,继续全局搜索 ShortcutType 这个枚举类
在全局搜索的时候需要留意一下,我们的目标是找到调用 normalize 方法的地方,所以需要寻找符合传参要求的地方,例如下面的红框处
定位到 ConfigurationService$ConfigurableBuilder#normalizeProperties 函数,根据前面的代码分析可得我们这里如果 this.properties 可控那么就可以最终控制 rawValue 从而控制 SPEL 表达式中的内容
然后发现在当前文件中的 bind 调用触发,但是可以看到在 bind函数 中并没有对 properties 进行赋值的操作,说明 properties 是在 bind 之前进行设置的
全局搜索 bind() 在查看 bind 的时候需要留意有对 properties 赋值的地方
我这里找了 RouteDefinitionRouteLocator#lookup 在函数中可以看到在 bind 前面对 properties 进行了设置,而 properties 是从 predicate 中进行获取的
向上查找找到 combinePredicates
再向上看可以发现 predicate 与 routeDefinition 有关
看到这里大致有个数,大概是路由中 与 predicates 相关可作为入口造成 RCE
0x02 结合官方文档
查询了一些资料了解到 predicates 能根据设置来对请求做校验处理
在官方文档中提供了配置各种校验的配置文件
为了验证猜想我就先修改配置文件来测试一下是否会触发,这里直接用官方的 demo ,发现能成功触发
(但是修改配置文件算什么 rce 啊 这不是自欺欺人吗)
所以查阅官方文档寻找能否支持添加路由的特性,发现 Actuator API 提供了有这个特性
我们可以通过 post 请求 http://localhost:8080/actuator/gateway/routes/{new route}
来添加路由
所以可以构造如下 payload
{
"id": "hacker",
"predicates": [{
"name": "Path",
"args": {"_genkey_0":"#{T(java.lang.Runtime).getRuntime().exec('open -a Calculator')}"}
}],
"filters": [],
"uri": "https://www.uri-destination.org",
"order": 0
}
创建完之后 refresh 一下就可以马上生效
ps:如果为了防止多次刷新,我们可以触发之后 delete 删除
可以问一下,在构造payload的时候,是如何知道哪个部分是spel的参数吗,是一个一个的手动去调试尝试吗?还是有其他的技巧可以知道,希望师傅可以解答
首先这个漏洞的利用手法是通过创建一个含有恶意spel语法的路由来进行利用的,关于师傅说的如何知道哪个部分是spel参数这个我没怎么明白,创建路由的手法可以从官方文档中查询获得