是否有任何标准库方法可以过滤掉包含特殊遍历序列的路径,例如../
和所有其他复杂形式的向上目录遍历,以保护文件路径API输入不会向上遍历 给定的" root"路径?
我有一个包含根文件夹值成员的类,以及一个接受递归删除路径的成员函数。我的目标是使这个API安全,过滤掉提供给它的任何输入路径 - 这将转换为根文件夹值的路径向上。目的是这个类将被广泛用于删除根路径下的文件,但它永远不会触及根路径上的任何东西。
这类似于更广泛的path traversal attack。
限制性太强的方法(即可能导致漏报)可能适用于我的特定用例,如果这简化了事情,而且,我目前的需求是文件系统路径而不是网络路径(尽管是一个Web模块)为了相同的缘故,理论上可以在这里工作)。
答案 0 :(得分:16)
您可以使用Path.normalize()
从路径中删除“..”元素(及其前面的元素) - 例如它会将“a / b /../ c”变成“a / c”。请注意,它不会在路径的开头处删除“..”,因为它也没有要删除的前一个目录组件。因此,如果您要预先添加另一条路径,请先执行此操作,然后将结果标准化。
您还可以使用Path.startsWith(Path)
检查一条路径是否是另一条路径的后代。而且Path.isAbsolute()
毫不奇怪地告诉你,路径是绝对的还是相对的。
以下是我如何处理进入API的不受信任路径:
/**
* Resolves an untrusted user-specified path against the API's base directory.
* Paths that try to escape the base directory are rejected.
*
* @param baseDirPath the absolute path of the base directory that all
user-specified paths should be within
* @param userPath the untrusted path provided by the API user, expected to be
relative to {@code baseDirPath}
*/
public Path resolvePath(final Path baseDirPath, final Path userPath) {
if (!baseDirPath.isAbsolute()) {
throw new IllegalArgumentException("Base path must be absolute")
}
if (userPath.isAbsolute()) {
throw new IllegalArgumentException("User path must be relative");
}
// Join the two paths together, then normalize so that any ".." elements
// in the userPath can remove parts of baseDirPath.
// (e.g. "/foo/bar/baz" + "../attack" -> "/foo/bar/attack")
final Path resolvedPath = baseDirPath.resolve(userPath).normalize();
// Make sure the resulting path is still within the required directory.
// (In the example above, "/foo/bar/attack" is not.)
if (!resolvedPath.startsWith(baseDirPath)) {
throw new IllegalArgumentException("User path escapes the base path");
}
return resolvedPath;
}
答案 1 :(得分:1)
您无需使用第三方库来执行此操作。 Java提供的文件API使您能够验证文件是否是另一个文件的后代。
Path.resolve(String)将解析父目录引用,绝对路径和相对路径。如果将绝对路径作为参数传递给resolve方法,则返回绝对路径。它不保证返回的值是调用方法的路径的后代。
您可以使用Path.startsWith(Path)方法检查路径是否是其他路径的后代。
Path root = java.nio.file.Files.createTempDirectory(null);
Path relative = root.resolve(pathAsString).normalize();
if (!relative.startsWith(root)) {
throw new IllegalArgumentException("Path contains invalid characters");
}
当pathAsString
包含对父目录的引用或是绝对路径时,relative
可以引用root
中未包含的文件。在这种情况下,您可以在允许对文件进行任何修改之前抛出异常。