WebClient不得提供本地文件

时间:2017-07-24 13:15:43

标签: c# asp.net security

我有一个简单的反向代理,以避免浏览器中的CORS。 从本质上讲,它的工作原理如下:

string url = Request.QueryString["url"];
using (var webClient = new System.Net.WebClient())
{
    byte[] buffer = webClient.DownloadData(url);
    Response.Clear();
    Response.BinaryWrite(buffer);
}

用法:

/reverseproxy.aspx?url=http%3A%2F%2Fexample.com%2F

然而,这有一个漏洞。以下请求将返回我的IIS服务器的日志。

/reverseproxy.aspx?url=c%3A%2Finetpub%2Flogs%2FLogFiles%2FW3SVC1%2Fu_ex170712.log

有没有办法告诉WebClient 不提供本地文件? 未设置权限且未使用File.Exists(url)

2 个答案:

答案 0 :(得分:1)

您可以创建一个额外的程序集,为WebRequestconfigure your web.config创建自己的实现,以便将自定义实现用于文件协议。

以下是您的需求:

工厂

此课程决定reqest uri是否为本地,如果需要,请添加您自己的支票。

public class NoLocalFile: IWebRequestCreate
{
    public WebRequest Create(Uri uri)
    {
            // add your own extra checks here
            // for example what Patrick offered in his answer
            // I didn't test if I can't create a local UNC path
            if (uri.IsFile && !uri.IsUnc)
            {
                // this is a local file request, we're going to return something safe by 
                // creating our own custom WebRequest
                return (WebRequest) new NoLocalFileRequest(); 
            }
            else
            {
                // this should allow non local file request
                // if needed
                return FileWebRequest.Create(uri);
            }
    }
}

NoLocalFileRequest

这是我们的自定义WebRequest

所需的最小实现
public class NoLocalFileRequest:WebRequest
{
    // return an instance of our custom webResponse
    public override WebResponse GetResponse()
    {
        return new NoLocalFileResponse();
    }
}

NoLocalFileResponse

此类实现WebResponse并返回带有字符串" NO!"的ASCII表示形式的内存流。这里也需要实现ContentLength属性。

public class NoLocalFileResponse : WebResponse {

    static byte[] responseBytes = Encoding.ASCII.GetBytes("NO!");

    public override long ContentLength
    {
        get {
            return responseBytes.Length;
        }
        set {              
            // whatever
        }
    }

    public override Stream GetResponseStream()
    {
        // what you want to return goes here
        return new MemoryStream(responseBytes);
    }
}

如果将这些类放在名为MyCustomWebRequests的命名空间中并将其编译为名为BlockLocalFile.dll的程序集,请将该程序集复制到Web应用程序的bin文件夹中,然后您只需要创建或添加这些更改到你的web.config:

<system.net>
  <webRequestModules>
    <remove prefix="file:"/>
    <add prefix="file:" type="MyCustomWebRequests.NoLocalFile, BlockLocalFile"/>
  </webRequestModules>
</system.net>

当你测试这个时,你会发现你以前的代码仍然没有改变,而尝试本地文件技巧的浏览器会得到&#34; NO!&#34;返回而不是您的文件内容。

请注意,此配置更改适用于在该Web应用程序的appdomain中运行的所有代码。如果您的合法代码也需要正常使用文件协议,则必须更改工厂方法,以决定要创建哪个WebRequest。

答案 1 :(得分:0)

您可以使用Uri类检查您提供的URI是URL还是文件引用。您可以使用找到的代码here

private static bool IsLocalPath(string p)
{
  return new Uri(p).IsFile;
}

更安全的方法是检查scheme的{​​{1}}是否与Urihttp匹配:

https