我知道可靠的安全建议,即避免接受用户输入,然后选择用于读取/写入文件的路径。但是,假设您有一个基本目录(例如ftp文件夹的根目录),那么如何最好地确保给定的用户输入使我们保持在该文件夹中?
例如,
Path.Combine(_myRootFolder,_ myUserInput)
仍然可以将我们带到_myRootFolder之外。这也可能是狡猾的
newPath = Path.Combine(_myRootFolder,_ myUserInput) if(newPath.StartsWith(_myRootFolder)) ......
从用户处获得类似“/back/to/myrootfolder/../../and/out/again”的内容。有什么策略?我错过了一个可以使用的明显的.NET方法吗?
答案 0 :(得分:6)
在ASP.NET应用程序中,您可以使用Server.MapPath(filename)
,如果生成的路径超出应用程序根目录,则会引发异常。
如果你想要的只是一个安全的文件名而你只想要那里的所有文件就变得更简单了;
FileInfo file = new FileInfo(
Server.MapPath(
Path.Combine(@"c:\example\mydir", filename)));
如果您在ASP.NET之外表示可以使用Path.GetFullPath
。
string potentialPath = Path.Combine(@"c:\myroot\", fileName);
if (Path.GetFullPath(potentialPath) != potentialPath)
// Potential path transversal
或者您调用Path.GetFullPath,然后检查它的开头是否与您要锁定的目录相匹配。
答案 1 :(得分:1)
我相信Path.FullPath会做你需要的(虽然我没有测试过):
string newPath = Path.Combine(_myRootFolder, _myUserInput);
string newPath = Path.FullPath(newPath);
if (newPath.StartsWith(_myRootFolder)) ...
答案 2 :(得分:1)
我知道,这个帖子已经过时了,但为了防止读者编写带有潜在安全错误的代码,我想我应该指出,Path.Combine(arg1, arg2)
使用arg2
时不能保存{{1}直接基于用户输入。
以arg2
为例," C:\ Windows \ System32 \ cmd.exe" arg1
参数将被完全忽略,您可以授予API或服务器应用程序用户对整个文件系统的完全访问权限。
因此请谨慎使用此方法!
我提出了这个应该(afaik)安全的解决方案:
public static string SecurePathCombine(params string[] paths)
{
string combinedPath = "";
foreach (string path in paths)
{
string newPath = Path.Combine(combinedPath, path);
if (!newPath.StartsWith(combinedPath))
return null;
combinedPath = newPath;
}
if (Path.GetFullPath(combinedPath) != combinedPath)
return null;
return combinedPath;
}
答案 3 :(得分:0)
好吧,在您的FTP服务器示例中,您应该设置用户主目录和权限,以便它们无法导航到文件夹之外。你有什么理由不能这样做吗?
答案 4 :(得分:-1)
您可以解析输入字符串并使用正则表达式剪切../。