CVE-2022-22947

https://github.com/vulhub/vulhub/blob/master/spring/CVE-2022-22947/README.zh-cn.md

https://paper.seebug.org/1878/

https://sourcegraph.com/github.com/spring-cloud/spring-cloud-gateway/-/commit/d8c255eddf4eb5f80ba027329227b0d9e2cd9698?visible=2

概述

Spring Cloud Gateway Actuator API SpEL表达式注入命令执行(CVE-2022-22947)

Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞,当攻击者可以访问Actuator API的情况下,将可以利用该漏洞执行任意命令。

分析

关键字StandardEvaluationContext

org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue

entryValue 被解析为 spel,然后往上倒追

可以找到ShortcutType的三个枚举值的normalize中调用了getValue 方法,entry 是取自 args 中

在倒追到org.springframework.cloud.gateway.support.ConfigurationService.ConfigurableBuilder#normalizeProperties,上面 args 的传参是this.properties

此时开始分叉,需要追踪两方面,一个是如何触发,一个是如何控制传参,这里明显不是一步到位的。

首先追踪如何触发,可以看到有很多 Controller 可以触发,但是没有找到往上refresh,因为 refresh 对应的是一个事件,可能这个事件可以异步刷新。

gateway/routes/{id}
gateway/routes
gateway/routes/{id}/combinedfilters

然后就是追踪可控点,也就是追踪properties

org.springframework.cloud.gateway.support.ConfigurationService.AbstractBuilder#properties

倒追最后可以到org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getRoutes

但是可以看到它是链式调用,所以实际上传递到 convertToRoute 里面的内容是this.routeDefinitionLocator.getRouteDefinitions()的结果,跟进去看一下

这里实现有很多,我以org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository#getRouteDefinitions为例看一下,可以看到是取的 routes 里面的内容,然后找一下这个值是如何变动的

org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository#save

然后追踪到路由gateway/routes/{id}

org.springframework.cloud.gateway.actuate.AbstractGatewayControllerEndpoint#save

修复分析

自定义一个GatewayEvaluationContext替代StandardEvaluationContext,本质是 SimpleEvaluationContext