Path.Combine的安全版本
-
03-07-2019 - |
题
我有一个我信任的 rootPath
和一个我没有的 relativePath
。我想以这样的方式组合它们,以确保结果在 rootPath
下,并且用户不能使用 ..
来回到起点点。我做希望相对路径允许以下内容: hello \ .. \ world
== world
解决方案
要展开:使用Path.Combine,然后对结果调用GetFullPath并检查该结果是否以rootPath开头。
它不会保护你免受硬链接的侵害,但它应该捕捉到双点等简单的东西。
以上代码:
string Resolve(string fileName)
{
string root = FileRoot();
string ret = Path.GetFullPath(Path.Combine(root, fileName));
if (ret.StartsWith(root.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar)) return ret;
throw new ArgumentException("path resolved to out of accesable directroy");
}
其他提示
您只需调用 Path.GetFullPath()
,然后检查它是否以您信任的 rootPath
开头。如果您倾向于偏执,请检查 rootPath
是否已植根。
public Boolean IsPathSafe(String rootPath, String relativePath)
{
return rootPath.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
Path.IsPathRooted(rootPath) &&
Patch.Combine(rootPath, relativePath).GetFullPath().StartsWith(rootPath);
}
有关第一次测试的解释,请参阅Alex Martelli对technophile答案的评论。
你可以做的一件事就是计算反斜杠的数量( \
)和双点( ..
),并确保双倍的数量 - 点小于反斜杠的数量。为了超越文件夹结构中的 rootPath
,你需要至少与双点一样多的反斜杠 - 因此,如果你只允许 relativePath
至少还有一个反斜杠,你应该是安全的。
不隶属于 StackOverflow