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请求添加路由时在filters的args参数中注入恶意SpEL表达式。

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

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

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

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

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

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

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

执行结果回显
vulhub - CVE-2022-22947中使用的filter为AddResponseHeader过滤器,其为Spring Cloud Gateway内置的28个过滤器工厂之一,作用是为原始响应添加Header。

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

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