Java代码审计深度解析:文件上传漏洞与组合攻击全指南
字数 1078 2025-08-22 12:23:06
Java代码审计深度解析:文件上传漏洞与组合攻击全指南
一、文件上传漏洞核心原理
文件上传漏洞的本质是未对用户上传的文件进行有效校验,导致攻击者可上传恶意文件。其危害包括:
- 恶意文件执行:上传Webshell实现RCE(远程代码执行)
- 存储型XSS:通过上传HTML/SVG文件触发跨站脚本攻击
- 服务端资源耗尽:超大文件导致DoS(拒绝服务)
- 敏感信息泄露:覆盖配置文件获取敏感信息
- 组合攻击入口:为其他漏洞利用提供支撑
二、高危文件上传函数全解析
1. 基础IO操作相关
① java.io.File + lastIndexOf/indexOf
漏洞代码示例:
String fileName = request.getParameter("filename");
int lastIndex = fileName.lastIndexOf(".");
String ext = fileName.substring(lastIndex + 1);
if(ext.equalsIgnoreCase("jpg")) {
File file = new File("/uploads/" + fileName); // 路径遍历风险
// 保存文件...
}
攻击Payload:
filename="../../WEB-INF/web.xml"
修复方案:
Path resolvedPath = Paths.get("/uploads/")
.resolve(fileName)
.normalize();
if(!resolvedPath.startsWith("/uploads/")) {
throw new SecurityException("非法路径");
}
② FileOutputStream
漏洞代码:
try(InputStream is = request.getInputStream();
FileOutputStream fos = new FileOutputStream("/uploads/" + fileName)) {
// 保存文件...
}
安全方案:
String safeName = UUID.randomUUID() + ".jpg";
Files.copy(is, Paths.get("/uploads/", safeName));
2. Apache Commons FileUpload组件
① DiskFileItemFactory
错误配置:
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File("/tmp/uploads")); // 目录可执行风险
修复方案:
File tempDir = new File(System.getProperty("java.io.tmpdir"));
factory.setRepository(tempDir);
② ServletFileUpload
漏洞代码:
List<FileItem> items = new ServletFileUpload(factory).parseRequest(request);
for (FileItem item : items) {
if (!item.isFormField()) {
String fileName = item.getName(); // 未过滤../等特殊字符
File file = new File(uploadDir, fileName);
item.write(file);
}
}
3. Spring框架相关
① MultipartFile
漏洞示例:
public String upload(@RequestParam("file") MultipartFile file) {
if(file.getContentType().equals("image/jpeg")) {
file.transferTo(new File("/uploads/" + file.getOriginalFilename()));
}
return "success";
}
绕过方法:修改请求头Content-Type为image/jpeg上传PHP文件
修复方案:
byte[] header = new byte[4];
file.getInputStream().read(header);
if(!Arrays.equals(header, new byte[]{(byte)0xFF, (byte)0xD8, (byte)0xFF, (byte)0xE0})) {
throw new InvalidFileException();
}
② CommonsMultipartResolver
错误配置:
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(-1); // 无限制
安全配置:
resolver.setMaxUploadSize(1024 * 1024 * 10); // 10MB
resolver.setMaxInMemorySize(4096);
4. 其他高危函数
① getRealPath
危险用法:
String savePath = request.getServletContext().getRealPath("/uploads");
File file = new File(savePath, fileName); // 可能覆盖系统文件
安全建议:
String fixedPath = "/opt/app/uploads";
② getInputStream
风险代码:
try (InputStream is = request.getInputStream()) {
Files.copy(is, Paths.get("/uploads/", fileName)); // 未校验文件内容
}
三、组合攻击场景深度剖析
- 文件上传 + RCE:上传Webshell后执行系统命令
- 文件上传 + XSS:上传恶意HTML/SVG文件触发跨站脚本
- 文件上传 + XXE:上传包含XXE攻击载荷的文件
- 文件上传 + CSRF:结合CSRF漏洞实现自动上传
四、防御策略
1. 输入验证层
- 文件扩展名白名单校验
- 文件内容类型校验(检查文件头魔数)
- 文件名规范化处理
2. 存储处理层
- 使用随机生成的文件名
- 文件存储目录设置适当权限
- 文件内容二次处理(如重采样图片)
3. 安全配置层
- 限制上传文件大小
- 设置安全的临时目录
- 禁用危险的文件执行权限
4. 输出防护层
- 设置正确的Content-Disposition头
- 对用户下载的文件进行安全检查
- 实施内容安全策略(CSP)
五、检测方法
-
静态代码扫描规则:
- 检查直接使用用户输入作为文件路径
- 检查未经验证的文件上传逻辑
- 检查危险的文件操作函数调用
-
动态Fuzz测试:
- 尝试上传各种恶意文件类型
- 测试路径遍历Payload
- 验证文件大小限制是否生效