webclient DownloadData安全漏洞?

webclient DownloadData security flaw?

看这段代码:

public static void Main()
{
    try
    {
        WebClient client = new WebClient();
        byte[] data = client.DownloadData("http://website../../../page/1/2021-02/28/01/2021022801_brief.jpg");
        Console.WriteLine("data: " + data.Length);
    }
    catch(Exception exc)
    {
        Console.WriteLine(exc);
    }
}

运行 它在 .NET fiddle 上(例如),你会得到这个异常:

System.Net.WebException: Could not find a part of the path 'C:\Resources\directory49ebba6307418392168ca985d98463.DotNetFiddle.Web.LocalResources\Sandboxbe885b-8fe4-40d0-b80e-cc2cfcbebfbe\page21-0221022801_brief.jpg'. ---> System.Net.WebException: Could not find a part of the path 'C:\Resources\directory49ebba6307418392168ca985d98463.DotNetFiddle.Web.LocalResources\Sandboxbe885b-8fe4-40d0-b80e-cc2cfcbebfbe\page21-0221022801_brief.jpg'. ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Resources\directory49ebba6307418392168ca985d98463.DotNetFiddle.Web.LocalResources\Sandboxbe885b-8fe4-40d0-b80e-cc2cfcbebfbe\page21-0221022801_brief.jpg'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
   at System.Net.FileWebStream..ctor(FileWebRequest request, String path, FileMode mode, FileAccess access, FileShare sharing, Int32 length, Boolean async)
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, FileAccess access, Boolean asyncHint)
   --- End of inner exception stack trace ---
   at System.Net.FileWebResponse..ctor(FileWebRequest request, Uri uri, FileAccess access, Boolean asyncHint)
   at System.Net.FileWebRequest.GetResponseCallback(Object state)
   --- End of inner exception stack trace ---
   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   at System.Net.WebClient.DownloadData(Uri address)
   at System.Net.WebClient.DownloadData(String address)
   at Program.Main() in d:\Windows\Temp\vbu5djxg.0.cs:line 13

您看到本地服务器路径了吗?!这怎么可能? URI 以 http 开头,为什么 .NET 会尝试在本地查找文件?

此外,如果用户输入 URL,他们可以访问服务器文件夹信息...这不是安全漏洞吗?

http://website../../../page/1/2021-02/28/01/2021022801_brief.jpg 不是有效的 URI。 DownloadData that takes a string eventually calls a helper 的重载具有将字符串转换为 URI 的这段代码:

    if (!Uri.TryCreate(path, UriKind.Absolute, out uri))
        return new Uri(Path.GetFullPath(path));

调用 Uri.TryCreate 将失败,因为 website.. 的 FQDN 无效。由于它失败了,它回落到 Path.GetFullPath

从那里开始,您将深入向后兼容工作和假设,将您的字符串视为 / 分隔字符串和有效路径,并将其附加到当前工作目录。然后它作为 file:// URI 冒泡,当本地文件无法打开时,它会失败并显示您看到的错误。

如果您在接受 URI 的用户输入的情况下,我建议您使用 Uri.TryCreateUriKind.Absolute 自己构建 URI,并验证类型是您支持的类型之一(通常只是 HTTP 和 HTTPS)。任何其他你应该视为错误并绕过一些辅助层的东西。