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 的影响版本如下

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图1

直接去到 Github 查看 commit 记录,可以很快定位到漏洞修补代码

https://github.com/spring-cloud/spring-cloud-gateway/commit/818fdb653e41cc582e662e085486311b46aa779b

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图2

下载源码 3.1 的代码可以直接定位到漏洞处,ShortcutConfigurable#getValue

可以看到如果 rawValue 如果是 #{ 开头同时 } 结尾,就会进入到 SPEL 解析的部分

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图3

找到了漏洞点之后我们只需要向上查找调用就可以了,发现在当前文件的 ShortcutType 中调用了 getValue 获取值,继续全局搜索 ShortcutType 这个枚举类

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图4

在全局搜索的时候需要留意一下,我们的目标是找到调用 normalize 方法的地方,所以需要寻找符合传参要求的地方,例如下面的红框处

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图5

定位到 ConfigurationService$ConfigurableBuilder#normalizeProperties 函数,根据前面的代码分析可得我们这里如果 this.properties 可控那么就可以最终控制 rawValue 从而控制 SPEL 表达式中的内容

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图6

然后发现在当前文件中的 bind 调用触发,但是可以看到在 bind函数 中并没有对 properties 进行赋值的操作,说明 properties 是在 bind 之前进行设置的

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图7

全局搜索 bind() 在查看 bind 的时候需要留意有对 properties 赋值的地方

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图8

我这里找了 RouteDefinitionRouteLocator#lookup 在函数中可以看到在 bind 前面对 properties 进行了设置,而 properties 是从 predicate 中进行获取的

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图9

向上查找找到 combinePredicates

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图10

再向上看可以发现 predicate 与 routeDefinition 有关

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图11

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图12

看到这里大致有个数,大概是路由中 与 predicates 相关可作为入口造成 RCE

0x02 结合官方文档

https://docs.spring.io/spring-cloud-gateway/docs/3.1.0/reference/html/#gateway-request-predicates-factories

查询了一些资料了解到 predicates 能根据设置来对请求做校验处理

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图13

在官方文档中提供了配置各种校验的配置文件

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图14

为了验证猜想我就先修改配置文件来测试一下是否会触发,这里直接用官方的 demo ,发现能成功触发

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图15

(但是修改配置文件算什么 rce 啊 这不是自欺欺人吗)

所以查阅官方文档寻找能否支持添加路由的特性,发现 Actuator API 提供了有这个特性

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图16

我们可以通过 post 请求 http://localhost:8080/actuator/gateway/routes/{new route} 来添加路由

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图17

所以可以构造如下 payload

  1. {
  2. "id": "hacker",
  3. "predicates": [{
  4. "name": "Path",
  5. "args": {"_genkey_0":"#{T(java.lang.Runtime).getRuntime().exec('open -a Calculator')}"}
  6. }],
  7. "filters": [],
  8. "uri": "https://www.uri-destination.org",
  9. "order": 0
  10. }

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图18

创建完之后 refresh 一下就可以马上生效

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图19

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图20

ps:如果为了防止多次刷新,我们可以触发之后 delete 删除

Spring Cloud GateWay CVE-2022-22947 SPEL RCE - 图21