6

我创建了这个 HTTP 处理程序来更新本地 SQL Express 数据库中的信息。

我意识到用户可以使用相对 URI 路径“/../../file.zip”作为查询字符串,并且能够在受限区域之外下载文件。

该站点尚未上线,因此现在不是安全问题,但我真的很想阻止这样的事情。

我添加了一个简单的 string.replace 行,从输入查询中删除任何“..”。

我还应该在这里做些什么来确保这一点?

public void ProcessRequest(HttpContext context)
{
    string filesPath = "C:/Downloads/";
    string fileName = context.Request.QueryString["filename"];
    fileName = fileName.Replace("'", "''").Replace("..", "").Replace("/", "").Replace("\\", "");

    if (!string.IsNullOrEmpty(fileName) && File.Exists(filesPath + fileName))
    {
        context.Response.ContentType = "application/octet-stream";
        context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename=\"{0}\"", fileName));
        context.Response.WriteFile(filesPath + fileName);
        //Do work to update SQL database here
    }
    else
    {
        context.Response.ContentType = "text/plain";
        context.Response.Write(filesPath + fileName + " Invalid filename");
    }
}
4

2 回答 2

10

我通常使用这个简单的代码来检查这个问题:

(我直接输入,可能编译不出来,只是给你个思路)

private string getPath(string basePath, string fileName)
{
    var fullPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(basePath, fileName));
    if (fullPath.StartsWith(basePath))
        return fullPath;
    return null;
}

目标是使用Path.GetFullPath. 此方法会将任何 /../ 等转换为完整路径。然后检查返回的路径是否在允许的目录中。
请注意,此方法可能会返回与预期略有不同的路径,请阅读MSDN了解详细说明

于 2013-04-10T14:59:31.657 回答
2

Request.QueryString["filename"]实际上可能是代表文件的键。如果您不希望用户能够轻松猜测文件密钥,则密钥可以是数字或随机字符串。您可以将映射存储在数据库中,并使用密钥来检索本地文件名(如果您想让两者不同并真正隐藏您的实现细节,则可能是显示文件名)。

于 2013-04-10T15:18:27.380 回答