删除文件时检查文件路径

时间:2013-01-03 18:29:40

标签: c# asp.net .net

如果我有一个web方法,在调用时删除文件,它接受三个参数(cNum,year和fileName)。我是否需要担心这种方法的漏洞利用。我唯一能想到的就是使用..\..\..\来进一步推动删除文件夹结构。这应该很容易删除。但还有什么我应该担心的吗?

[WebMethod(EnableSession = true, 
           Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
    try
    {
        if (String.IsNullOrEmpty(cNum) 
            || String.IsNullOrEmpty(year) 
            || String.IsNullOrEmpty(fileName))
                throw new Exception();

        string path = Server.MapPath(@"~\docs\custFiles\" 
                                        + year + @"\" 
                                        + cNum + @"\" + fileName);
        File.Delete(path);
    }
    catch
    {
        throw new Exception("Unable to delete file");
    }
    return true;
}

3 个答案:

答案 0 :(得分:12)

我建议使用GetFileName method上的Path class清除文件名参数,如下所示:

public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
    // Cleanse fileName.
    fileName = Path.GetFileName(fileName);

GetFileName方法从路径中删除所有目录信息,这正是您要在此处执行的操作。

输入如:

..\..\..\filename.ext

你会得到:

filename.ext

作为回报,您不必担心会有人注入一个会逃脱您所定位目录的路径(假设此文件名是用户输入的,或者来自开放端点,有人可以输入他们想要的任何输入)

然后,您可以将自定义路径附加到fileName

当然,如果您的所有文件都在预定义的目录中,那么这只会起作用。

但是,要做任何事情来处理删除用户无权访问的文件。如果这些文件属于该目录中的另一个用户,则此处不会检查是否属于这种情况(但如果所有用户都有权删除这些文件,那么它是确定)。

此外,您可能希望使用Path类上的Combine method来合并您的路径,例如:

string path = Server.MapPath(@"~\docs\custFiles\")
path = Path.Combine(path, year);
path = Path.Combine(path, cNum);
path = Path.Combine(path, fileName);

如果您使用的是.NET 4.0或更高版本,则可以使用the overload of the Combine method that takes the parts of the path as a parameter array

string path = Path.Combine(
    Server.MapPath(@"~\docs\custFiles\"),
    year, cNum, fileName);

最后,作为Shai points out,如果可能(对于完整的解决方案),为了使这更加安全,您应该在文件系统级别启用权限。

如果您模仿用户或使用受限制的用户帐户来处理所有请求,那么您应该授予该用户仅访问~\docs\custFiles\目录(以及任何子目录)的权限。

以上 该用户帐户应具有 no 访问权限的目录。

答案 1 :(得分:1)

如果文件名和目录名是有效的文件名,最好检查它们,检查这个char数组:

Path.GetInvalidFileNameChars

修改

你应该也可以像这样验证年份和数字:

bool valid = int.TryParse(num, out temp);

答案 2 :(得分:1)

您可能还需要考虑在文件系统上使用内置安全性来防止用户删除不需要的目录中的文件。如果Web应用程序在具有仅在一个目录中删除文件的权限的特定用户下运行,则无论用户尝试什么,该应用程序都无权执行删除。

此外,这将使维护(即:添加新目录)变得非常简单,而无需重新部署应用程序。

然后,您可以捕获尝试访问无效访问尝试,并根据需要对其执行某些操作。

[WebMethod(EnableSession = true, 
    Description = "Method for deleting files uploaded by customers")]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
public Boolean deleteCustFiles(string cNum, string year, string fileName)
{
    try
    {
        if (String.IsNullOrEmpty(cNum) || String.IsNullOrEmpty(year) ||
            String.IsNullOrEmpty(fileName))
            throw new Exception();
        string path = 
            Server.MapPath(@"~\docs\custFiles\" + year + @"\" + cNum + 
                @"\" + fileName);
        File.Delete(path);
    }
    catch (System.Security.SecurityException e)
    {
        throw new Exception("Unauthorized attempt to delete file");
    }
    catch
    {
        throw new Exception("Unable to delete file");
    }

    return true;
}