【问题标题】:Is Path Traversal Vulnerabilities possible in my below code?我的以下代码中是否可能存在路径遍历漏洞?
【发布时间】:2016-05-23 05:23:57
【问题描述】:

任何人都可以确认,路径遍历漏洞是否可能在我下面的代码 sn-p 中?如果是,那么我应该做些什么改变。

[RedirectingAction]
public ActionResult Download(string fileName)
{
    byte[] fileBytes = System.IO.File.ReadAllBytes(Server.MapPath("~/ClientDocument/") + fileName);
    return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

【问题讨论】:

  • filename 来自哪里?
  • 文件名来自查询字符串

标签: c# security


【解决方案1】:

是的,它很脆弱。

为了证明这一点,我建立了一个名为 WebApplication1.sln 的新 MVC 项目

以下请求下载解决方案文件:

http://localhost:56548/Home/Download?fileName=../../WebApplication1.sln

你可以写一个幼稚的检查:

private static readonly char[] InvalidFilenameChars = Path.GetInvalidFileNameChars();
public ActionResult Download(string fileName)
{
    if (fileName.IndexOfAny(InvalidFilenameChars) >= 0)
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

    var rootPath = Server.MapPath("~/ClientDocument/");
    byte[] fileBytes = System.IO.File.ReadAllBytes(Path.Combine(rootPath, fileName));
    return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

这将检查fileName 参数是否为有效文件名。此排除目录分隔符,因此它们不能将路径作为文件名传递。

但是,完全安全的唯一方法是限制您的应用程序拥有的权限。只授予它对您的虚拟目录的权限,而不是其他权限。

【讨论】:

  • Path.GetDirectoryName 也可用于验证目录是否为预期目录。
  • 没有那么脆弱。这仅适用于项目在开发服务器上运行,使用开发人员的凭据。默认情况下,应用程序池帐户无权访问站点根目录之外
  • 但这并不意味着它没问题 - AccessDenied 异常会花费 CPU,这意味着它们会花费托管和云资金。别介意浪费时间检查错误日志。应执行文件检查以减少日志噪音和服务错误请求的成本
  • @PanagiotisKanavos “默认情况下”是一个相当宽泛的说法,实际上完全取决于您使用的 Web 服务器...例如,运行 dotnet core 在您调用它的用户下运行因为,它很可能可以访问 web 目录之外的文件。
  • @Rob 在这种情况下,无论如何都不应该将路径与用户输入结合起来。 Accept an ID or other indicator 并在代码本身中找到正确的路径
【解决方案2】:

从概念上讲,为了缓解路径遍历漏洞,您应该做的是评估您的 basePath 到它的真实路径,同样对您的 basePath 和文件名执行相同的操作。如果第二个操作的结果文件仍在您的 basePath 文件夹中,则您知道路径遍历尚未发生。

我使用的是更高版本的 .NET,因此 Server.MapPath 无效。结果,我不确定这是否适合您;但这至少说明了如何在概念上解决它:

[RedirectingAction]
public ActionResult Download(string fileName)
{
    var baseFolder = Path.GetFullPath(Server.MapPath("~/ClientDocument/"));
    var targetFile = Path.GetFullPath(Path.Combine(baseFolder, fileName));
    if(targetFile.StartsWith(baseFolder){
      byte[] fileBytes = System.IO.File.ReadAllBytes(Server.MapPath("~/ClientDocument/") + fileName);
      return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
    } else {
      //Don't do the download and do something else.
    }  
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多