我信任rootPath
而我信任relativePath
。我希望以这样的方式组合它们,以确保结果在rootPath
下,并且用户无法使用..
来回到起点。我做希望相对路径允许以下内容:hello\..\world
== world
答案 0 :(得分:6)
要展开:使用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");
}
答案 1 :(得分:2)
您可以致电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答案的评论。
答案 2 :(得分:-1)
您可以做的一件事是计算反斜杠的数量(\
)和双点(..
),并确保双点的数量小于反斜杠。为了超越文件夹结构中的rootPath
,你需要至少与双点一样多的反斜杠 - 因此,如果你只允许relativePath
s至少多一个反斜杠,你应该安全。