使用Path.Combine时的C#Path遍历警告

时间:2018-02-13 23:51:51

标签: c# security json.net

我目前正在使用NewtonJSON从JSON文件加载一些UI数据。但是,有一个警告说我有路径遍历。

情况如下: Ed Morton's answer

有任何想法要删除此安全漏洞吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

当用户或其他不受信任的源提供的路径与父路径组合在一起而不进行检查时,可以进行路径遍历攻击。问题是路径的“路径遍历”组件可以导出父文件夹。

例如,如果要组合以下两个路径,绝对路径和相对路径:

Base/absolute path: C:\WebData
Relative/user path: ..\windows\system32\

然后这会产生:

C:\windows\system32\

您可以想象,让某人读取或写入此目录(这不是预期的WebData目录)可能是一个巨大的问题,因为它可能会导致某人了解您的系统信息或放置妥协的漏洞该系统将其控制给恶意行为者。

你可以read more about this exploit

要正确处理此漏洞,您需要确保与父路径相结合的相对路径是安全的。以下是确保这一点的一些方法:

  • 相对路径来自已知的受信任来源,例如经过审核的内部列表。
  • 之前已检查过相对路径,并以确保可以将其与不受信任的路径区分开来的方式进行存储/维护,并且同时无法由用户或不受信任的代理进行修改。例如,将路径保留在字符串中是的想法。相反,你会做一些事情,比如创建一个TrustedPath类,代码只能获得一个实例运行代码,检查路径是否安全。
  • 组合后检查相对路径,确保其位于正确的位置。

你可以这样做最后一项:

  1. (作为避免不必要的异常的良好做法),使用Path. GetInvalidFileNameChars()检查无效字符的(不可信的)相对路径。
  2. 按照您的要求执行Path.Combine()
  3. 确保生成的路径仍在原始父路径中。这可以通过简单地确保生成的路径以父路径开始来完成,但可能存在问题。因此,请考虑an answer like this或其他代码,以确保生成的路径真正是所需文件夹的后代。
  4. 完成所有这些操作后,如果仍显示“路径遍历”警告,则可以使用代码质量/安全检查工具中的菜单选项将此路径遍历实例注释为安全。您可能还想在注释中添加注释,说明您将其标记为安全的原因,可以想象包含此SO问题的链接或其答案之一。

    注1:小心重用已证明的相对路径与特定的绝对路径相结合。请考虑以下事项:

    Base/absolute path: C:\WebData\FormElements\SuperForm\windows\
    Relative/user path: ..\windows\
    

    这两条路径可以安全地组合,但是这并未证明相对路径始终可以安全地与任何绝对路径一起使用。

    注2:要小心你怎么做。假设相对路径遍历始终以..\开头是错误的。以下是有效的相对路径:folder\..\..\wheeeWeGotOut

答案 1 :(得分:-1)

下一个使用Path.Combine的安全方法是

    public string PathCombine(string path1, string path2)
    {
        if (path2.Contains("..")) return null;
        if (path2.Contains(":")) return null;

        string result = Path.Combine(path1, path2);

        return (result.Equals(path2) ? null : result);
    }

请注意,这仅是一个示例,可以改进不允许的字符串检查。 作为其他信息,您可以看看here。 如果您想获得有关如何利用此问题的更多信息,建议您阅读OWASP documentation

检查结果是否类似于第二个参数的事实是由于CombineInternal函数的行为所致,您可以在此处进行检查:

    private static string CombineInternal(string first, string second)
    {
        if (string.IsNullOrEmpty(first))
            return second;

        if (string.IsNullOrEmpty(second))
            return first;

        if (IsPathRooted(second.AsSpan()))
            return second;

        return JoinInternal(first.AsSpan(), second.AsSpan());
    }

如您所见,如果第二个变量是IsPathRooted,结果将是它,并且这是无需使用'..'字符即可将其爆炸的常见方法,请考虑以下示例:

您的网站位于c:\ wwwroot \ web1 \ public \ index.html 如果作为第二个参数c:\ wwwroot \ web1 \ private \ secret.conf传递,则将可以访问此文件。