Request Web Page in c# spoofing the Host

后端 未结 9 1299
攒了一身酷
攒了一身酷 2020-12-01 06:10

I need to create a request for a web page delivered to our web sites, but I need to be able to set the host header information too. I have tried this using HttpWebRequest,

9条回答
  •  一整个雨季
    2020-12-01 06:28

    Necromancing.
    For those still on .NET 2.0
    It is in fact quite easy, if you know how.

    Problem is, you can't set the host header, because the framework won't let you change the value at runtime. (.net framework 4.0+ will let you override host in a httpwebrequest).

    Next attempt will be setting the header with reflection - as demonstrated in the top upvoted answer here - to get around it, which will let you change the header value. But at runtime, it will overwrite this value with the host part of the url, which means reflection will bring you nothing, which is why I don't understand why people keep upvoting this.

    If the dns-name doesn't exist, which is quite frankly the only case in which you want to do this in the first place, you can't set it, because .NET can't resolve it, and you can't override the .NET DNS resolver.

    But what you can do, is setting a webproxy with the exact same IP as the destination server.

    So, if your server IP is 28.14.88.71:

    public class myweb : System.Net.WebClient
    {
        protected override System.Net.WebRequest GetWebRequest(System.Uri address)
        {
            System.Net.WebRequest request = (System.Net.WebRequest)base.GetWebRequest(address);
            //string host = "redmine.nonexistantdomain.com";
    
            //request.Headers.GetType().InvokeMember("ChangeInternal",
            //    System.Reflection.BindingFlags.NonPublic |
            //    System.Reflection.BindingFlags.Instance |
            //    System.Reflection.BindingFlags.InvokeMethod, null,
            //    request.Headers, new object[] { "Host", host }
            //);
    
            //server IP and port
            request.Proxy = new System.Net.WebProxy("http://28.14.88.71:80");
    
            // .NET 4.0 only
            System.Net.HttpWebRequest foo = (System.Net.HttpWebRequest)request;
            //foo.Host = host;
    
            // The below reflection-based operation is not necessary, 
            // if the server speaks HTTP 1.1 correctly
            // and the firewall doesn't interfere
            // https://yoursunny.com/t/2009/HttpWebRequest-IP/
            System.Reflection.FieldInfo horribleProxyServicePoint = (typeof(System.Net.ServicePoint))
                .GetField("m_ProxyServicePoint", System.Reflection.BindingFlags.NonPublic |
                System.Reflection.BindingFlags.Instance);
    
            horribleProxyServicePoint.SetValue(foo.ServicePoint, false);
            return foo; // or return request; if you don't neet this
        }
    
    
        }
    

    and voila, now

    myweb wc = new myweb();
    string str = wc.DownloadString("http://redmine.netexistantdomain.com");
    

    and you get the correct page back, if 28.14.88.71 is a webserver with virtual name-based hosting (based on http-host-header).

    Now you have the correct answer to the original question, for both WebRequest and WebClient. I think using custom sockets to do this would be the wrong approach, particularly when SSL should be used, and when an actual solution is that simple...

提交回复
热议问题