Spring Core rce漏洞分析(CVE-2022-22965)
漏洞描述:
Springmvc框架参数绑定功能,绑定了请求里的参数造成变量注入,攻击者可以实现任意文件写入,漏洞点spring-beans包中。
漏洞编号:
CVE-2022-22965
影响范围:
JDK>=9
spring < 5.3.18 or spring < 5.2.20
tomcat
前置知识:
ClassLoader:
Class文件是编译好的,可以在jvm虚拟机中直接运行的字节码文件,ClassLoader类加载器负责把class类根据需求,动态地加载到jvm虚拟机中运行。
与反射的区别:
Java中两种加载class到jvm中的方式,都是通过类的全名来加载类。其加载过程分为以下三个步骤:
- 装载:(loading)找到class对应的字节码文件。
- 连接:(linking)将对应的字节码文件读入到JVM中。
- 初始化:(initializing)对class做相应的初始化动作。
- Class.forName("className");
调用方式为:Class.forName(className, true, ClassLoader.getCallerClassLoader())
className:需要加载的类的名称。
true:是否对class进行初始化(需要initialize)
classLoader:对应的类加载器
- ClassLoader.laodClass("className");
调用方式为:ClassLoader.loadClass(name, false)
name:需要加载的类的名称
false:这个类加载以后是否需要去连接
两种方式的区别是forName()得到的class是已经初始化完成的,loadClass()得到的class是还没有连接的。
BeanWrapper:
BeanWrapper是Spring的JavaBeans结构的中央结果可以,相当于一个用于分析和操作标准JavaBean结构的代理。拥有获取和设置属性值和属性描述符的功能。这里Spring的JavaBean的属性注入特性,也是导致漏洞的根本原因。
PropertyDescriptor:
属性描述器,BeanWrapper通过他可以获取JavaBean某个单独的属性。主要方法:
getPropertyType(),获得属性的Class对象;
getReadMethod(),获得用于读取属性值的方法;
getWriteMethod(),获得用于写入属性值的方法;
public static void setProperty(UserInfo userInfo, String userName) throws Exception {
// 获取bean的某个属性的描述符
PropertyDescriptor propDesc = new PropertyDescriptor(userName, UserInfo.class);
// 获得用于写入属性值的方法
Method methodSetUserName = propDesc.getWriteMethod();
// 以Key:Value格式写入属性值
methodSetUserName.invoke(userInfo, "zhangsan");
System.out.println("set userName:" + userInfo.getUserName());
}
CachedIntrospectionResults:
专门用于缓存JavaBean的PropertyDescriptor描述信息的类。
环境配置:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<packaging>war</packaging>
<groupId>com.example</groupId>
<artifactId>spring4shell-vulnerable-application</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring4Shell Vulnerable Application</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.6.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>helloworld</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.3</version>
</plugin>
</plugins>
</build>
</project>
漏洞分析:
漏洞的利用,简而言之就是在你前端提交参数key=value给服务端,由服务端的controller来解析。
Payload分析:
目前已知的漏洞利用条件要求必须使用tomcat,利用tomcat的日志写入模块,我们可以在tomcat的配置文件server.xml中看到该模块的配置参数信息,和Payload一致:


核心利用点就在于调用AccessLogValve来修改tomcat的日志文件,从而实现任意文件写入,详细调用链分析如下。
漏洞调试:
spring以kv格式传入一个参数,会被绑定到其目标对象上去,而这个对象是动态获取的,我们在获取对象的地方打断点:
org.springframework.beans.BeanWrapperImpl#getCachedIntrospectionResults
这个方法会先判断缓存中是否存在目标对象,不存在则新建一个,然后返回这个目标对象,我们看一下目标对象是如何获取到的:

这里的forclass返回当前包装的类,读取Class的内容,读取的时候先从缓存里读,有的话直接返回,没有就新建一个cache加入缓存里。

看返回的cachedIntrospectionResults的值,返回一个属性描述器pd,pd能修改和读取目标对象的值。

断点下在org.springframework.beans.BeanWrapperImpl#getLocalPropertyHandler

用[和.进行分割,分割出的第一个属性为class,保存在nestedProperty中,后续属性保存在nestedPath中。


这里使用了get方法对比class属性是否存在于org.springframework.beans.CachedIntrospectionResults的这个属性描述器中,如存在则获取对应实例,进行后续的参数注入操作。


接下来,我们再发一个payload追踪一下属性描述器propertyDescriptors的值的获取途径:
在getCachedIntrospectionResults中会判断是否有nestedProperty缓存,如果没有就新建一个,如果有就获取其信息。


org.springframework.beans.CachedIntrospectionResults中使用put操作查询本地的类名,这里虽然对属性描述器查询的值做了检查,不过是只限制了class类的classLoader属性,而使用module调用classLoader属性就绕过了这里的检查。

而在获取缓存的时候,会使用java.lang.Object.getClass(),从而获取到class,进而就能利用反射执行所有注入的数据了。
结合这个payload就是:
- 调用HelloWorld的getClass() 拿到Class对象
- 通过class对象调用getModule()
- 通过Module调用getClassLoader()
- 通过ClassLoader拿resources
- context是Tomcat的StandardContext
- parent拿到的是StandardEngine
- pipeline拿到的是StandardPipeline
- first拿到的是AccessLogValve
目前公开的利用链也就是pipeline下的AccessLogValue的利用,这个类用来设置日志存储参数,包括路径、后缀,修改参数即可达到写入任意文件的目的。
补丁分析:
CVE-2010-1622绕过:
这个漏洞本质上是2010年Spring对象绑定漏洞(CVE-2010-1622)补丁的一种绕过,之前漏洞的修复方式是:禁止class对象直接获取classLoader方法,这种补丁当时是没有什么问题的,这也是本漏洞仅出现在jdk9以上版本的原因。

因为在jdk9引入的moudle机制中,其中module.classloader绕过了之前的补丁,这里直接通过class.module的classLoader加载了key:value格式的请求类,从而产生了后续的漏洞利用。

补丁修复:
我们分析一下spring5.3.18版本的修复手法,我们通过diff spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java可以看到:

这里进一步限制了class对象获取classLoader,调用class.Class方法时,只允许调用名称为Name结尾的方法(比如setName、getName)。且加入了对其调用的属性的返回值的判断,不能为classLoader或者classLoader的子类。
Spring Core rce漏洞分析(CVE-2022-22965)的更多相关文章
- Windows RDP的RCE漏洞分析和复现(CVE-2019-0708)
0x00 漏洞描述 Windows系列服务器于2019年5月15号,被爆出高危漏洞,该漏洞影响范围较广如:windows2003.windows2008.windows2008 R2.windows ...
- Joomla 3.0.0 - 3.4.6 RCE漏洞分析记录
0x00 前言 今天早上看到了国内几家安全媒体发了Joomla RCE漏洞的预警,漏洞利用的EXP也在Github公开了.我大致看了一眼描述,觉得是个挺有意思的漏洞,因此有了这篇分析的文章,其实这个 ...
- Sunlogin RCE漏洞分析和使用
介绍 前两天网上曝出了关于向日葵远控工具(Sunlogin)Windows个人版的RCE漏洞POC.因为利用简单并且网上出现了公开的自动化扫描脚本,所以测试的人很多,也出现了一些真实攻击.漏洞的问 ...
- 向日葵远程RCE漏洞分析及漏洞利用脚本编写
0x00 漏洞概述 向日葵是一款免费的,集远程控制电脑.手机.远程桌面连接.远程开机.远程管理.支持内网穿透等功能的一体化远程控制管理软件.如果想要手机远控电脑,或者电脑远控手机可以利用向日葵:如果是 ...
- Struts2-057/CVE-2018-11776两个版本RCE漏洞分析(含EXP)
0x01 前言 2018年8月22日,Apache Strust2发布最新安全公告,Apache Struts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由Sem ...
- Nuxeo 认证绕过和RCE漏洞分析(CVE-2018-16341)
简介 Nuxeo Platform是一款跨平台开源的企业级内容管理系统(CMS).nuxeo-jsf-ui组件处理facelet模板不当,当访问的facelet模板不存在时,相关的文件名会输出到错误页 ...
- Struts S2-048 RCE漏洞分析
应该是S2-048目前最详细的一篇了.. 漏洞影响 Struts 2.3.x系列中的Showcase应用 使用了struts1 插件,并在使用ActionMessages时将客户端可控的参数拼接传递给 ...
- Spring Cloud Gateway actuator组建对外暴露RCE问题漏洞分析
Spring Cloud gateway是什么? Spring Cloud Gateway是Spring Cloud官方推出的第二代网关框架,取代Zuul网关.网关作为流量的,在微服务系统中有着非常作 ...
- ref:Spring Integration Zip 不安全解压(CVE-2018-1261)漏洞分析
ref:https://mp.weixin.qq.com/s/SJPXdZWNKypvWmL-roIE0Q 0x00 漏洞概览 漏洞名称:Spring Integration Zip不安全解压 漏洞编 ...
随机推荐
- es5 es6 新增
es5的新特性 对于数组和字符串都进行了加强 map 遍历 es6的新特性 数组的增强 find 查找findIndex 查找下标 字符的增强 includes 是否包含 (包含返回true 不包含返 ...
- 【java】学习路径17-StringBuffer、StringBuilder的使用与区别
本文讲解StringBuffer和StringBuilder的使用与区别. 1-- String String类型我们已经很熟悉了,String一旦被赋值,其在堆中的数据便无法修改. 平时我们的&qu ...
- 【c#语言简单算法】1-角谷猜想
角谷猜想 算法目的 一个正整数x,如果是奇数就乘以3再加1,如果是偶数就析出偶数因数2ⁿ,这样经过若干个次数,最终回到1. 这里计算0-100的所有计算过程 代码实现 for (int n = 1; ...
- 第七十六篇:ref引用(在vue中引用Dom的方法)
好家伙, 引子: jQuery简化了程序员操作DOM的过程 vue 优势:MVVM 在vue中,程序员不需要操作DOM.程序员只需要把数据维护好即可!(数据驱动视图) 那么若要在vue中操作dom,这 ...
- C语言:多功能计算器程序说明书
好家伙,3000字终于写完了 一.题目:多功能科学计算器 二.内容: (1)概述或引言 开发环境为Visual C++ 目前已实现的功能: (1)解二元一次方程.一元二次方程 (2)进行矩阵相加.相减 ...
- 手写tomcat——有线程池化能力的servlet 服务
点击查看代码 public class DiyTomcat { private int port = 8080; public static final HashMap<String, DiyS ...
- Hive数据仓库工具基本架构和入门部署详解
@ 目录 概述 定义 本质 特点 Hive与Hadoop关系 Hive与关系型数据库区别 优缺点 其他说明 架构 组成部分 数据模型(Hive数据组织形式) Metastore(元数据) Compil ...
- 常用MySQL语句(持续更新)
1. 客户端登录 在终端输入 mysql -u[用户名] -p[密码] 2. 数据库级别操作 // 创建数据库 create database [db name]; // 查看数据库列表 show d ...
- ES6中的箭头函数与普通函数的区别
箭头函数与普通函数的区别 1.语法上更加简洁.清晰 基本语法: // 关于箭头函数的参数 // 如果箭头函数没有参数,直接写一个括号即可 let fun1 = () => { console.l ...
- 如何调试 Docker
开启 Debug 模式 在 dockerd 配置文件 daemon.json(默认位于 /etc/docker/)中添加 { "debug": true } 重启守护进程. $ s ...