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表达式的执行结果。
结语: 本文如有错误,敬请斧正。