【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造

渗透技巧 2年前 (2022) admin
639 0 0
漏洞信息


Spring Cloud Gateway 是基于 Spring Framework 和 Spring Boot 构建的 API 网关,它旨在为微服务架构提供一种简单、有效、统一的 API 路由管理方式。


近日VMware官方发布了Spring Cloud Gateway存在SPEL表达式注入漏洞CVE-2022-22947,可导致未授权远程命令执行漏洞:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


漏洞影响版本:


  • Spring Cloud Gateway < 3.1.1

  • Spring Cloud Gateway < 3.0.7

  • Spring Cloud Gateway 其他已不再更新的版本


下面将在深入分析漏洞原理的同时,通过构建命令回显和内存马两种方式来探索漏洞的武器化利用。

漏洞分析


可以从Github下载存在漏洞的版本v3.1.0,然后用idea载入:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


从漏洞通报来看,这是一个SPEL表达式注入漏洞,对比补丁`org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue`:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


新版本将`getValue`函数中的`StandardEvaluationContext`替换成了`SimpleEvaluationContext`,从而修复了SPEL表达式注入。寻找`getValue`函数被调用的情况:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


只在枚举值`ShortcutType`的三个取值(`DEFAULT`、`GATHER_LIST`、`GATHER_LIST_TAIL_FLAG`)中被调用:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


三个调用类似,以`DEFAULT`为例,继续寻找调用关系:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


一直定位到`RouteDefinitionLocator#convertToRoute`:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


尝试根据`RouteDefinition`提取`GatewayFilter`列表。这里的调用和路由以及过滤规则有关,查看Spring Cloud Gateway路由相关的接口定义:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


定位处理控制器`org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint`:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


POST输入参数为`RouteDefinition`类型,与上面调用链中的`convertToRoute`函数的输入参数类型一致。


查看`RouteDefinition`定义:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


注意列表型变量`FilterDefinition`的定义:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


参考`RouteDefinition`变量的定义很容易出构造POST测试请求:


POST /actuator/gateway/routes/123456 HTTP/1.1Host: 127.0.0.1:9000Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 166
{ "id": "id", "filters": [{ "name": "123456", "args": {} }], "uri": "http://localhost"}


触发断点:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


首先会通过函数`validateRouteDefinition`对参数进行了检查:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造

进入验证函数`isAvailable`:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


代码中会验证`Filter`的`name`属性是否合法,合法列表整理如下:


class org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.CacheRequestBodyGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RemoveRequestParameterGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SetRequestHostHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactoryclass org.springframework.cloud.gateway.filter.factory.RequestHeaderSizeGatewayFilterFactory


可以随意选择其中的一个`GatewayFilterFactory`,比如利用`Retry`来修改请求包:


POST /actuator/gateway/routes/123456 HTTP/1.1Host: 127.0.0.1:9000Accept-Encoding: gzip, deflateAccept: */*Accept-Language: enUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36Connection: closeContent-Type: application/jsonContent-Length: 181
{ "id": "1234567", "filters": [{ "name": "Retry", "args": {"a":"payload" } }], "uri": "http://localhost"}


请求后显示路由创建成功。可以通过refresh来生效:


POST /actuator/gateway/refresh HTTP/1.1Host: 127.0.0.1:9000Connection: close


成功触发表达式解析:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


RCE复现


换成RCE模式:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


武器化一:命令回显


通过调试发现,在refresh路由时会调用对应`GatewayFilter`的`apply`函数。当成功创建新的路由后,可以通过GET请求获取配置信息:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


回顾前面合法的`GatewayFilter`列表,我们发现存在一个名为`AddResponseHeaderGatewayFilterFactory`的子类:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


`apply`函数会将配置信息写入HTTP响应数据包中,所以可以尝试利用`AddResponseHeaderGatewayFilterFactory`来构造命令回显请求:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


refresh执行SPEL表达式,将结果写入HTTP响应流,然后访问创建的路由,可以将命令执行的结果回显出来:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


最后可以发送DELETE请求将创建的新路由删除。

武器化二:Spring Controller内存马


CVE-2022-22947是一个SPEL表达式注入漏洞,并且框架基于Spring Framework实现,所以我们考虑通过漏洞注入Spring内存马。Spring可以在Controller、Interceptor等不同层级构建不同的内存马,相关知识网上已经有多篇文章进行了详细讲解,参考如下:


spring-controller-内存马

https://su18.org/post/memory-shell/#spring-controller-内存马


本文尝试构造Spring Controller内存马。Spring可以通过`RequestMappingHandlerMapping`来完成`@Contoller`和`@RequestMapping`注解,这里有两个比较关键的类:


  • `RequestMappingInfo`:一个封装类,对一次http请求中的相关信息进行封装

  • `HandlerMethod`:对Controller的处理请求方法的封装,里面包含了该方法所属的bean、method、参数等对象


函数`RequestMappingHandlerMapping#registerHandlerMethod`可以将Controller函数与`RequestMappingInfo`对象关联起来。首先寻找`RequestMappingHandlerMapping`对象。我们可以尝试在内存中搜索,借助`java-object-searcher`搜索,结果如下:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


除了上面通过`Thread`的方式提取`RequestMappingInfo`之外,通过观察SPEL表达式解析的代码发现上下文环境存在`beanFactory`的对象:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


存有337个Bean对象信息,可以利用下面代码辅助打印结果:


for(int i = 0; i<((DefaultListableBeanFactory) beanFactory).beanDefinitionNames.toArray().length; i++){    System.out.println(((DefaultListableBeanFactory) beanFactory).beanDefinitionNames.toArray()[i]);}


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


直接利用SPEL上线文环境中的`beanFactory`即可获取`RequestMappingHandlerMapping`对象。SPEL表达式中可以过`@`来获取`BeanResolver`配置的beans对象:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


接下来创建内存马的过程就很简单了,最终效果就是将如下自定义的`Controller`子类通过SPEL表达式注入到内存并通过`RequestMappingHandlerMapping`对象完成路由注册:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


构造完新的payload后,发送数据包:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


refresh后将注入内存马:


【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造


最后同样记得发送DELETE请求将创建的路由删除。




点关注,不迷路!

【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造

关注公众号回复“漏洞”获取研究环境

原文始发于微信公众号(且听安全):【漏洞利用系列】漏洞武器化之CVE-2022-22947 Spring Cloud Gateway表达式注入回显与内存马构造

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...