CVE-2022-22947 Spring Cloud Gateway SPEL RCE 简单分析
前言
前段时间刚爆出来的洞,很多师傅都详细分析了各自的思路和想法,不过总要自己亲手去调试分析才能更好的进步,因此有了这篇文章
漏洞版本
|
|
环境搭建
地址:https://github.com/spring-cloud/spring-cloud-gateway/tree/v3.1.0
找到GatewaySampleApplication.java
启动即可
漏洞分析
先看一下commit删除的漏洞代码
https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e
可以看出这里会执行spel表达式,使用StandardEvaluationContext
显然是不安全的在加上参数外部可控导致了spel表达式注入,修复后使用了更安全的GatewayEvaluationContext
来解析spel表达式,直接来看一下org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue
会对#{}里面的内容进行spel解析,接下来进行回溯看一下哪里使用了getValue()
ShortcutType
是个枚举类,类中重写了三个normalize()
都调用了getValue()
,而在ShortcutConfigurable
接口类中有以下代码:
|
|
会去调用默认的normalize()
,然后对shortcutType()
进行回溯
在normalizeProperties()
中会对filer的属性进行解析,其中this.properties
是Expression expression = parser.parseExpression(entryValue, new TemplateParserContext());
中的entryValue
,然后一步一步转到getValue()
中进入SPEL表达式中触发命令,接着继续对this.properties
参数进行回溯
继续对properties()
进行回溯
这里有两个函数调用了properties()
并且进行了传参,一一对其回溯后,最终都回溯到了getRoutes()
中的this::convertToRoute
到这里后就很容易理解了,在添加新路由后会加载到filter中,其中某个参数最后进入到getValue()
中执行了SPEL表达式造成了注入
接下来来看一下官方文档
https://cloud.spring.io/spring-cloud-gateway/multi/multi__actuator_api.html
接下来就是构造新路由然后去触发漏洞,这里看了Y4er师傅的文章,找到了org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint#save
,在AbstractGatewayControllerEndpoint.java
中对路由进行增删操作
在增加路由时进行了校验,需要与filter进行匹配,也就是说在构造poc时新增已有的filter就可以触发漏洞,这里直接贴一张Y4er师傅的图
这里贴一下部分堆栈内容:
|
|
看完堆栈后,在
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#loadGatewayFilters
中,先进行了properties(definition.getArgs())
传参,然后进行了bind()
绑定路由
漏洞复现
直接通过burp抓包添加路由
然后直接refresh