Spring Cloud Gateway CVE-2022-22947 漏洞分析 | xxxSpring Cloud Gateway CVE-2022-22947 漏洞分析 – xxx
菜单

Spring Cloud Gateway CVE-2022-22947 漏洞分析

五月 31, 2022 - 白帽汇

Spring Cloud Gateway CVE-2022-22947 漏洞分析

Spring Cloud Gateway CVE-2022-22947 漏洞分析匿名者  1天前

作者:cdhe@白帽汇安全研究院

1、漏洞信息

当Gateway Actuator端点是启用状态并且是允许访问的以及相关配置不安全时,使用Spring Cloud Gateway的应用程序容易受到代码注入攻击。远程攻击者可以发出恶意制作的请求,允许在远程主机上进行任意远程执行。

https://tanzu.vmware.com/security/cve-2022-22947

Spring Cloud Gateway CVE-2022-22947 漏洞分析

1.1 、影响版本

Spring Cloud Gateway 3.1.0

Spring Cloud Gateway 3.0.0 – 3.0.6

不受支持的版本也会受到影响

1.2、漏洞补丁

https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e

Spring Cloud Gateway CVE-2022-22947 漏洞分析

通过查看修复补丁以及对比原文件,此修复的地方是ShortcutConfigurable接口的getValue方法中的StandardEvaluationContext类,将此类换成了GatewayEvaluationContext类,而GatewayEvaluationContext类是自定义的且继承EvaluationContext接口GatewayEvaluationContext
类内部是对SimpleEvaluationContext类的一些调用封装等。

StandardEvaluationContext类:支持更全面的SpEL功能

SimpleEvaluationContext类:基本的SpEL功能,仅支持 SpEL 语言语法的一个子集,例如排除对 Java 类型、构造函数和 bean 引用。

2、漏洞分析

2.1、调用链

环境可以直接下载对应版本然后载入ide运行即可

https://github.com/spring-cloud/spring-cloud-gateway/tags

直接开始从漏洞修复的地方看,也就是ShortcutConfigurable接口的getValue方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析

既然此处会被执行SpEL表达式,那就可以查看都有哪些地方对此进行调用,可以选中getValue
方法并且ctrl+alt+h即可查看被调用情况,可以看到有三个枚举常数对getValue方法进行调用并且都在ShortcutConfigurable接口中,而且三处都对normalize方法进行重写

Spring Cloud Gateway CVE-2022-22947 漏洞分析

继续向上追踪,查看哪些地方对normalize方法进行了调用,这次进入到了ConfigurationService类的内部类ConfigurableBuilder中的normalizeProperties方法,而normalizeProperties方法调用了normalize方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析

ConfigurationService类的内部类AbstractBuilder中的bind方法调用了normalizeProperties方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析

bind方法被五处地方所引用:

AbstractRateLimiter类中的onApplicationEvent方法

RouteDefinitionRouteLocator类中的loadGatewayFilters方法与lookup方法

WeightCalculatorWebFilter类中的handle方法

BetweenRoutePredicateFactoryTests类中的bindConfig方法

本次主要关注loadGatewayFilters方法,loadGatewayFilters方法继续向前路径为:loadGatewayFilters() -> getFilters() -> convertToRoute() -> getRoutes()

Spring Cloud Gateway CVE-2022-22947 漏洞分析

整个的调用链为

getValue:273, Spelexpression (org.springframework.expression.spel.standard)

getValue:60, ShortcutConfigurable (org.springframework.cloud.gateway.support)

normalize:94, ShortcutConfigurable$ShortcutType$1 (org.springframework.cloud.gateway.support)

normalizeProperties:140, ConfigurationService$ConfigurableBuilder (org.springframework.cloud.gateway.support)

bind:241, ConfigurationService$AbstractBuilder (org.springframework.cloud.gateway.support)

loadGatewayFilters:144, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route)

getFilters:176, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route)

convertToRoute:117, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route)

...

2.2、分析

首先getRoutes()调用convertToRoute方法并把参数routeDefinition传入,routeDefinition参数就是自定义的路由,而RouteDefinition的内容就是路由的语法格式

Spring Cloud Gateway CVE-2022-22947 漏洞分析

可以从toString方法看到数据字段的情况,而且filters字段是要求是ArrayList类型

Spring Cloud Gateway CVE-2022-22947 漏洞分析

Spring Cloud Gateway CVE-2022-22947 漏洞分析

之后定义了一个List<GatewayFilter>类型的gatewayFilters变量,其中GatewayFilter继承ShortcutConfigurable接口

Spring Cloud Gateway CVE-2022-22947 漏洞分析

之后调用getFilters方法并且传入自定义路由

Spring Cloud Gateway CVE-2022-22947 漏洞分析

首先判断是否有默认的filters,系统默认会有,所以(!this.gatewayProperties.getDefaultFilters().isEmpty())返回true,调用loadGatewayFilters设置默认的filters(!routeDefinition.getFilters().isEmpty())结果也是true,调用loadGatewayFilters方法传入id以及filters数组

Spring Cloud Gateway CVE-2022-22947 漏洞分析

传入到loadGatewayFilters方法后filters就成为了filterDefinitions,首先获取filterDefinitions的大小然后开启循环,将filterDefinitions中的数据放入definition,获取definition.getName放入factory,然后判断factory是否是null,如果是就抛出异常,提“Unable to find GatewayFilterFactory with name {filter}”,不是的话判断logger是否已开始debug模式,然后打印日志“RouteDefinition {id} applying filter {args} to {filter}”

Spring Cloud Gateway CVE-2022-22947 漏洞分析

定义变量configuration,通过加载definition参数,也就是传入的自定义路由,创建配置服务然后调用bind方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析

bind方法处主要是一些判断以及提示,判断configurationService的一些内容字段,比如configurable

是否为nullname等是否为null以及是否是空白等,(this.normalizedProperties == null) true,调用normalizeProperties方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析(this.service.beanFactory != null) true,调用normalize方法传入若干参数

Spring Cloud Gateway CVE-2022-22947 漏洞分析

args作为参数开启循环,argsMap<String, String>类型,然后取出keyvalue,其中key要求不能是“_genkey_”开头,否则就报错“Must not instantiate utility class.”以及其他几个并列要求,然后调用getValue方法

Spring Cloud Gateway CVE-2022-22947 漏洞分析

Spring Cloud Gateway CVE-2022-22947 漏洞分析

entryValue赋值给rawValueentryValue中的数据就是要执行的恶意代码,调用trim去除前后空格,判断rawValue是否为null以及是否“#{“开头和“}”结尾,设置context变量,将beanFactory
放入context.BeanResolver

Spring Cloud Gateway CVE-2022-22947 漏洞分析

Spring Cloud Gateway CVE-2022-22947 漏洞分析

调用parseexpression方法,对字符串做处理,最终把恶意字符串开头的“#{“和结尾的“}”去掉

Spring Cloud Gateway CVE-2022-22947 漏洞分析Spring Cloud Gateway CVE-2022-22947 漏洞分析

expression调用getValue方法,进入Spelexpression.class,判断context是否为空,获取compiledAst赋值给compiledAst其值为nullif语句为假没进入逻辑,调用expressionState方法,设置rootobject

Spring Cloud Gateway CVE-2022-22947 漏洞分析Spring Cloud Gateway CVE-2022-22947 漏洞分析

再次调用getValue方法,得到想要的结果

Spring Cloud Gateway CVE-2022-22947 漏洞分析

互联网上的利用代码大致相同,主要区别在于filtersname字段,根据上面的分析可以看出是对参数有各种判定以及要求的,那么在创建路由时也可能会进行判断或者说在那里能看到对name字段的对比判断

Spring Cloud Gateway CVE-2022-22947 漏洞分析

Spring Cloud Gateway CVE-2022-22947 漏洞分析

这里可以利用ide下方的Actoator中的映射功能查看创建路由对应的方法,这里就是AbstractGatewayControllerEndpoint.java中的save方法,可以直接在这里下断点

Spring Cloud Gateway CVE-2022-22947 漏洞分析

首先对传入的路由做格式化检查,然后调用validateRouteDefinition方法做内容检查

Spring Cloud Gateway CVE-2022-22947 漏洞分析Spring Cloud Gateway CVE-2022-22947 漏洞分析

validateRouteDefinition方法又调用isAvailable方法,其中对比恶意路由中自定义的filters.name是否在GatewayFilters.name

Spring Cloud Gateway CVE-2022-22947 漏洞分析

GatewayFilters.name一共29个

AddRequestHeader

MapRequestHeader

AddRequestParameter

AddResponseHeader

ModifyRequestBody

DedupeResponseHeader

ModifyResponseBody

CacheRequestBody

PrefixPath

PreserveHostHeader

RedirectTo

RemoveRequestHeader

RemoveRequestParameter

RemoveResponseHeader

RewritePath

Retry

SetPath

SecureHeaders

SetRequestHeader

SetRequestHostHeader

SetResponseHeader

RewriteResponseHeader

RewriteLocationResponseHeader

SetStatus

SaveSession

StripPrefix

RequestHeaderToRequestUri

RequestSize

RequestHeaderSize

之后两行语句还是进行对比,对比Predicates.name,漏洞原作者的自定义路由里对其进行了定义,没有这个也可以利用,调用isAvailable方法,对比Predicates.name是否在routePredicates.name

Spring Cloud Gateway CVE-2022-22947 漏洞分析

routePredicates.name一共13个

After

Before

Between

Cookie

Header

Host

Method

Path

Query

ReadBody

RemoteAddr

Weight

CloudFoundryRouteService

之后的if语句将判断返回值,如果自定义的name与系统要求的name不一致那么就返回报错信息

Spring Cloud Gateway CVE-2022-22947 漏洞分析

3、修复

3.1.x升级到3.1.1+

3.0.x升级到3.0.7+

不需要Gateway actuator endpoint的话可以management.endpoint.gateway.enabled: false 禁用它

或者在https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.endpoints.security设置保护措施

参考:

https://wya.pl/2022/02/26/cve-2022-22947-spel-casting-and-evil-beans/

https://tanzu.vmware.com/security/cve-2022-22947

本文为白帽汇原创文章,如需转载请注明来源:https://nosec.org/home/detail/5008.html


Notice: Undefined variable: canUpdate in /var/www/html/wordpress/wp-content/plugins/wp-autopost-pro/wp-autopost-function.php on line 51