Spring Cloud Gateway CVE-2022-22947 SpEL表达式注入

漏洞简介

Spring Cloud Gateway是Spring Cloud生态系统中的网关,Spring Cloud Gateway 皆在提供一种简单有效的API路由管理方式。其在3.1.0及3.0.6版本中存在SpEL表达式注入漏洞,当攻击者可访问Actuator API的情况下通过构造恶意路由并在filter(过滤器)参数中注入恶意的SpEL表达式时将导致攻击者可获取服务器权限。

漏洞利用

目前Vulhub已更新SpringCloudGateway的漏洞环境,使用CVE-2022-22947中的docker-compose.yml即可开启一个存在漏洞的Spring Cloud Gateway应用。


当攻击者可访问Actuator API的情况下通过/actuator/gateway/routes/{id}接口发送恶意的POST请求添加路由时在filtersargs参数中注入恶意SpEL表达式。

image-20220304002358872

201响应码表示该路由创建成功,当调用/actuator/gateway/refresh接口刷新时则会触发SpEL表达式的执行。

image-20220304002533385

漏洞分析

SpEL表达式注入漏洞位于org.springframework.cloud.gateway.support.ShortcutConfigurable接口中,该接口的getValue方法中判断如entryValue变量以#{前缀开头并以}后缀结尾的话则会将其作为表达式处理,而此处使用的context(上下文对象)为StandardEvaluationContext对象则导致了SpEL表达式注入漏洞。(使用SimpleEvaluationContext对象的话则只能执行受限的SpEL表达式,其不包括类型引用、构造函数、bean引用等)。

image-20220304004101945

首先在AbstractGatewayControllerEndpoint控制器的refresh方法下断点,RouteDefinitionRouteLocator#getFiltersfilter(过滤器)不为空时将调用loadGatewayFilters方法来加载filter。

image-20220304100101953

loadGatewayFilters中循环filterDefinitions列表并从gatewayFilterFactories中取出对应的filterFactory,然后调用ConfigurationService#bind方法,图中的definition.getName()definition.getArgs()为注册路由时传入的可控参数。

image-20220304101537362

bind中会判断filter的name不为空且properties不能为null,前者是注册路由时指定的filter名称,后者则是filter的参数,最后调用normalizeProperties方法。

image-20220304102136694

其通过ShortcutConfigurable#shortcutType方法ShortcutConfigurable$ShortcutType对象并调用normalize方法。

image-20220304102339516

ShortcutConfigurable$ShortcutType#normalize中循环传入的Map对象,将值的内容传入getValue方法中解析,最后判断当变量的值为#{开头并以}结尾则使用SpelExpressionParser解析器解析。

image-20220304102946636

执行结果回显

vulhub - CVE-2022-22947中使用的filterAddResponseHeader过滤器,其为Spring Cloud Gateway内置的28个过滤器工厂之一,作用是为原始响应添加Header

image-20220304104049236

当调用过滤器的apply方法时传入的AbstractNameValueGatewayFilterFactory$NameValueConfig对象中的value即为SpEL表达式的执行结果。

image-20220304104553449

结语: 本文如有错误,敬请斧正。

参考

vulhub/spring/CVE-2022-22947 at master · vulhub/vulhub

Java代码审计之SpEL表达式注入

CVE-2022-22947:SpEL Casting 和 Evil Beans – Wya.pl