title: C# Http Basic Authentication Bypass
body: <p>On a C# ASP.NET application, I've managed to bypass basic authentication (by sending the username/password through "Authorization" headers on a HTTPWebRequest) and I finally got the unlocked the target page that is protected by htaccess (located on a different server, basic auth) and sent the stream back to the browser.</p>
  
  <p>The issue appears as soon as the user clicks on a link, the basic auth logon box pops up again. We don't want the user to enter to username/password again.</p>
  
  <p>It seems that I need to be sending something back in the headers to tell the browser what username/password it's using for authorization.</p>
  
  <p>I've tried:</p>
  
  <ul>
  <li>Old "username:password@host" format (insecure, not allowed on IE anymore).</li>
  <li>HTTPWebRequest, which gives me the issue described before.</li>
  </ul>
  
  <p>Considerations:</p>
  
  <ul>
  <li>The remote server being accessed is a black box.</li>
  </ul>
  
  <p>Is there a way to achieve this? (It can be done in JavaScript as well).</p>
  
  <p>This is my function for the HttpRequest:</p>
  
  <pre><code>    public void DoWebRequest(String email, String psw, String hostname, 
      int port, String req_method, String webpage)
      {
  
      String path = hostname + ":" + port + "/" + webpage;
      String userdata = email + ":" + psw;
      System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
      byte[] data = encoding.GetBytes(path);
      byte[] authBytes = Encoding.UTF8.GetBytes(userdata.ToCharArray());
      String req_short_host_temp = hostname;
      String req_short_host = req_short_host_temp.Replace("http://", "");
  
      Uri uri = new Uri(path);
      HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri) as HttpWebRequest;
      req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705;)";
      req.Method = req_method;
      req.PreAuthenticate = false;
      req.Headers["Authorization"] = "Basic " + Convert.ToBase64String(authBytes);
      req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
      req.Headers.Add("Accept-Language: en-us,en;q=0.5");
      req.Headers.Add("Accept-Encoding: gzip,deflate");
      req.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
      req.KeepAlive = true;
      req.Headers.Add("Keep-Alive: 1000");
      req.ReadWriteTimeout = 320000;
      req.Timeout = 320000;
      req.Host = req_short_host;
      req.AllowAutoRedirect = true;
  
      req.ContentType = "application/x-www-form-urlencoded";
      req.Headers.GetType().InvokeMember("ChangeInternal", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, req.Headers, new object[] { "Host", req_short_host });
  
      var headers = new MyHeaderCollection();
      req.Headers = headers;
      headers.Set("Host", req_short_host);
  
      StreamWriter sw = new StreamWriter(req.GetRequestStream());
      sw.Write("/" + "?user=" + email + "&amp;password=" + psw);
      sw.Close();
  
      HttpWebResponse response = (HttpWebResponse)req.GetResponse();
      StreamReader reader = new StreamReader(response.GetResponseStream());
      string tmp = reader.ReadToEnd();
  
      foreach (Cookie cook in response.Cookies)
      {
          tmp += "\n" + cook.Name + ": " + cook.Value;
      }
  
      Response.Write(tmp);
      Response.End();
  
  }
  </code></pre>