低版本java.io.File类00截断分析
字数 1215 2025-08-25 22:58:55
Java.io.File类00截断漏洞分析与防御
漏洞概述
在低版本Java环境(特别是Java 1.6及以下版本)中,java.io.File类存在00截断漏洞(Null Byte Termination Vulnerability),攻击者可以利用此漏洞绕过文件后缀校验,实现任意文件下载或上传等安全风险。
漏洞原理
Java与C/C++字符串处理差异
- Java字符串:不以
\u0000(ASCII: 0x00)作为字符串结束标志,可以包含多个null字节 - C/C++字符串:以0x00作为字符数组/串的结束标志(宽字符以0x0000结尾)
底层机制分析
当Java代码调用File类相关方法时:
- Java层传递包含null字节的路径字符串到native层
- Native层将Java字符串转换为C/C++宽字符字符串(WCHAR*)
- 转换过程中,由于C/C++字符串以null字节结尾,导致null字节后的内容被截断
- 最终操作的文件路径不包含null字节后的内容(如硬编码的后缀)
版本差异分析
Java 1.6及以下版本
- 无null字节检查:
File类不检查路径中是否包含\u0000 - 存在截断风险:文件操作时null字节后的内容被丢弃
- 示例:
String bytes = "malicious\u0000.txt"; // 用户可控参数 File file = new File("/fixed/path/" + bytes); // 实际操作的文件路径为"/fixed/path/malicious"
Java 1.8及以上版本
- 新增安全检查:
File类增加了isInvalid()方法private boolean isInvalid() { if (status == null) { status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED : PathStatus.INVALID; } return status == PathStatus.INVALID; } - 严格校验:文件操作前调用
isInvalid()检查null字节,存在则抛出异常 - 安全增强:
FileInputStream、FileOutputStream等也间接调用此检查
攻击场景
任意文件下载
String taskID = request.getParameter("taskID"); // 用户可控
String path = "/fixed/dir/" + taskID + ".txt"; // 拼接硬编码后缀
File file = new File(path);
if(file.exists()) {
// 下载文件
}
攻击方式:
- 提供
taskID=../../etc/passwd\u0000 - Java 1.6环境下实际访问
/fixed/dir/../../etc/passwd - 硬编码的
.txt被截断
文件上传绕过
MultipartFile file = request.getFile("file");
String filename = file.getOriginalFilename();
File dest = new File("/upload/" + filename);
file.transferTo(dest);
攻击方式:
- 修改上传文件名包含null字节(如
shell.jsp\u0000.jpg) - Java 1.6环境下实际保存为
shell.jsp
防御措施
1. 升级Java版本
- 使用Java 1.8及以上版本,利用内置的null字节检查
2. 手动校验null字节
if (filename.indexOf('\u0000') != -1) {
throw new IllegalArgumentException("Filename contains null byte");
}
3. 路径标准化处理
File file = new File("/base/dir", userInput);
String canonicalPath = file.getCanonicalPath();
if (!canonicalPath.startsWith("/base/dir")) {
throw new IllegalArgumentException("Invalid path");
}
4. 文件上传特殊处理
- 使用
CommonsMultipartFile时:- 自动取最后一个文件分隔符后的字符串作为文件名
- 缓解跨路径上传风险
- 使用
Streams.checkFileName检查文件名(Apache Commons FileUpload)
5. 白名单校验文件后缀
String[] allowedExtensions = {".txt", ".pdf"};
boolean valid = false;
for (String ext : allowedExtensions) {
if (filename.toLowerCase().endsWith(ext)) {
valid = true;
break;
}
}
if (!valid) {
throw new IllegalArgumentException("Invalid file type");
}
总结
Java.io.File类00截断漏洞主要影响低版本Java环境,通过利用Java与C/C++字符串处理机制的差异,攻击者可绕过文件后缀校验。防御措施应结合版本升级、输入校验、路径标准化等多种手段,特别是在处理用户提供的文件路径时需格外谨慎。