部分路径遍历漏洞¶
ID: java/partial-path-traversal
Kind: problem
Security severity: 9.3
Severity: error
Precision: medium
Tags:
- security
- external/cwe/cwe-023
Query suites:
- java-security-extended.qls
- java-security-and-quality.qls
检查用户提供的路径 SUBDIR 是否位于目录 DIR 内的一种常用方法是使用 getCanonicalPath() 删除任何路径遍历元素,然后检查 DIR 是否为前缀。但是,如果 DIR 未以斜杠结尾,这可能会意外地允许访问 DIR 的同级目录。
另请参见 java/partial-path-traversal-from-remote,它类似于此查询,但仅标记具有远程可利用性证据的实例。
建议¶
如果用户应仅访问特定目录 DIR 内的项目,请确保在检查 DIR 是否为用户提供的路径 SUBDIR 的前缀之前,DIR 以斜杠结尾。注意,Java 的 getCanonicalPath() 返回一个**非**斜杠结尾的路径字符串,因此如果使用该方法,则必须向 DIR 添加斜杠。
示例¶
在本例中,if 语句检查 parent.getCanonicalPath() 是否是 dir.getCanonicalPath() 的前缀。然而,parent.getCanonicalPath() 并没有以斜杠结尾。这意味着用户提供的 dir 可能会被允许访问 parent 的兄弟节点,而不仅仅是 parent 的子节点,这是一个安全问题。
public class PartialPathTraversalBad {
public void example(File dir, File parent) throws IOException {
if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath())) {
throw new IOException("Path traversal attempt: " + dir.getCanonicalPath());
}
}
}
在本例中,if 语句检查 parent.toPath() 是否是 dir.normalize() 的前缀。由于 Path#startsWith 正确地检查了 dir 是否是 parent 的子节点,因此用户将无法访问 parent 的兄弟节点,如预期的那样。
import java.io.File;
public class PartialPathTraversalGood {
public void example(File dir, File parent) throws IOException {
if (!dir.toPath().normalize().startsWith(parent.toPath())) {
throw new IOException("Path traversal attempt: " + dir.getCanonicalPath());
}
}
}
参考资料¶
OWASP:部分路径遍历.
CVE-2022-23457: ESAPI 漏洞报告.
常见弱点枚举:CWE-23.