Path.Combine的安全版本

时间:2009-04-29 23:17:25

标签: .net relative-path path-manipulation

我信任rootPath而我信任relativePath。我希望以这样的方式组合它们,以确保结果在rootPath下,并且用户无法使用..来回到起点。我希望相对路径允许以下内容:hello\..\world == world

3 个答案:

答案 0 :(得分:6)

System.IO.Path.GetFullPath

要展开:使用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至少多一个反斜杠,你应该安全。