代码之家  ›  专栏  ›  技术社区  ›  Luke Vo

验证以防止路径字符串转到父文件夹

  •  1
  • Luke Vo  · 技术社区  · 7 年前

    我的业务逻辑是接受文件夹路径字符串来读取文件夹/文件。但是,根据安全规定,用户只能访问该文件夹。例如:

    他们的文件夹是:C:\foo\user\bar,他们可以访问 C:\foo\user\bar\data\.a.b..txt 通过 https://www.example.com/download?path=data/.a.b..txt

            var result = this.ResultFolder; // The user folder (\user\bar as in the example)
    
            if (!string.IsNullOrEmpty(path))
            {
                path = path.Replace("/", @"\");
    
                if (path.StartsWith(@"\"))
                {
                    path = path.Substring(1);
                }
    
                if (path.StartsWith('\\') || path.Contains("..\\"))
                {
                    throw new InvalidDataException("Forbidden Path.");
                }
    
                result = Path.Combine(result, path);
            }
    

    基本上,我做的是:

    • 请求允许路径以\开头,不计算任何内容。

    • 现在如果用户试图恶意(使用 \\ 或者尝试使用 ..\ (使用前注意) .. 仅限,但大小写为false,因为它是有效的文件/文件夹名)

    是否正确和安全?有什么框架方法可以帮助解决这个问题吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Flydog57    7 年前

    这里有一个解决方案 Path.GetFullPath(string path) :

    创建此函数:

    private static bool VerifyPathUnderRoot(string pathToVerify, string rootPath = ".")
    {
        var fullRoot = Path.GetFullPath(rootPath);
        var fullPathToVerify = Path.GetFullPath(pathToVerify);
        return fullPathToVerify.StartsWith(fullRoot);
    }
    

    然后可以用如下代码进行测试:

     var paths = new[]
     {
         "somepath/somefile.xxx",
         "..\\somepath/somefile.xxx",
         @"C:\this\that\the.other",
     };
     foreach (var path in paths)
     {
         var isOk = VerifyPathUnderRoot(path);
         var okString = isOk ? "OK" : "No";
         Debug.WriteLine($"{okString}: {path}");
     }
    

    这将导致调试器的输出窗格中出现以下情况:

    OK: somepath/somefile.xxx
    No: ..\somepath/somefile.xx
    No: C:\this\that\the.other
    

    我用 GetFullPath