如何修复Java中PDF下载场景的Path Manipulation漏洞?
路径操纵(Path Manipulation)漏洞修复方案
问题场景
Controller类的Get方法调用downloadPdf方法;ServiceImpl类的downloadPdf方法实现如下:
downloadPdf (fileName) { pdfFilePath = path + "/PDF/" FileInputStream fs = new FileInputStream (new File(pdfFilePath + fileName)) }上述代码存在路径操纵漏洞,请问该如何修复?我目前的思路是:获取pdfFilePath或fileName或两者的getCanonicalPath,与预期路径进行对比;或者使用某个validatePath方法来修复,是否可行?
你的思路完全可行,这正是修复路径操纵漏洞的核心方向,下面具体说两种可落地的实现方式:
1. 利用getCanonicalPath()做路径校验
通过获取文件的规范路径,和你预期的允许目录(比如固定的/xxx/PDF/)做比对,彻底拦截用户传入fileName中包含的../这类跳转路径。示例代码如下:
downloadPdf (fileName) throws IOException { String pdfDirPath = path + "/PDF/"; // 用父目录+文件名的方式创建File对象,避免字符串拼接的潜在问题 File targetFile = new File(pdfDirPath, fileName); // 获取规范路径,自动消除../、./等相对路径标识 String canonicalFile = targetFile.getCanonicalPath(); String canonicalDir = new File(pdfDirPath).getCanonicalPath(); // 校验目标文件是否严格处于允许的目录内 if (!canonicalFile.startsWith(canonicalDir + File.separator)) { throw new IllegalArgumentException("非法的文件请求"); } FileInputStream fs = new FileInputStream(targetFile); }
这里用File.separator是为了适配Windows和Linux不同的路径分隔符,避免硬写/导致跨系统问题。
2. 自定义validatePath方法校验文件名
如果不想处理复杂的路径比对,也可以直接对fileName本身做规则校验:
- 禁止包含任何路径分隔符(
/或\) - 禁止包含
../、./这类相对路径标识 - 可选:限制文件名只能使用合法字符(比如字母、数字、下划线、点号)
示例的校验方法和调用逻辑如下:
private boolean validatePath(String fileName) { // 拦截相对路径和路径分隔符 if (fileName.contains("../") || fileName.contains("./") || fileName.contains("/") || fileName.contains("\\")) { return false; } // 可选:限制文件名的合法字符范围 String validPattern = "^[a-zA-Z0-9_\\.]+$"; return fileName.matches(validPattern); } // 在downloadPdf中调用校验 downloadPdf (fileName) { if (!validatePath(fileName)) { throw new IllegalArgumentException("非法的文件名"); } String pdfFilePath = path + "/PDF/"; FileInputStream fs = new FileInputStream(new File(pdfFilePath, fileName)); }
额外注意事项
- 优先选择第一种路径校验方案,它能覆盖所有路径跳转的场景,比单纯校验文件名更彻底
- 尽量使用
new File(parentDir, fileName)的构造方法创建文件对象,比直接字符串拼接更安全 - 确保程序运行的用户对目标PDF目录只有读权限,避免因漏洞被利用后产生意外的写入操作
内容的提问来源于stack exchange,提问作者Pragati
相关产品推荐
相关产品推荐

