401 Error on HttpWebRequest with NTLM Authentication
Due to a security update to SMB that fixes a remote code execution vulnerability, you may experience 401.1 or 401.2 errors in certain situations while performing a WebRequest to one of your servers. This is because part of the security update institutes a loopback check on the authentication requests to prevent replay attacks. The Microsoft KB article refers to a few different scenarios where you can see authentication problems after applying this patch, but the one I’m most interested in is when you start getting 401 errors after an HttpWebRequest on an ASP.Net page.
The issues I experienced were while creating a page to display general status of one of my companies Sharepoint servers. The main issue which is the meat of this article was when I switched the authentication over to use NTLM instead of Digest, which broke my script. Everything I had in place should have worked, but the previously mentioned security update slipped under the radar and it took a while to figure out what was going on. You can do a basic web request on a server with Basic authentication by doing the following:
Dim _response As String Dim _auth As String = "Basic" Dim _uri As Uri = New Uri("http://my.domain.local/my-page.aspx") Dim _req As HttpWebRequest = WebRequest.Create(_uri) Dim _cc As CredentialCache = New CredentialCache() Dim _res As HttpWebResponse Dim _sr As StreamReader _cc.Add(_uri, _auth, New NetworkCredential("username", "password", "domain")) _req.PreAuthenticate = True _req.Credentials = _cc.GetCredential(_uri, _auth) _res = _req.GetResponse _sr = New StreamReader(_res.GetResponseStream) _response = _sr.ReadToEnd _sr.Close()
That code works perfectly well with Basic and even Digest(if you change the _auth value) authentication, however it will most likely not work for you if you are using NTLM authentication and your server has had the MS08-068 patch applied to it. Prior to discovering the conflict with this patch I went through a lot of effort to investigate the issue. One of the most useful debugging utilities in IIS7 is the failed request tracing logs. These logs give you really great insight as to what is going on inside your web request traffic. You can also use a tool like Fiddler to try and see what’s happening, but unfortunately because our Sharepoint server was live, it would have caused SSL certificate issues if I put it in the mix in my situation.
After looking at the failed request traces logs, I noticed an interesting difference between one of the failed requests from my health check script and a purposely failed request through a web browser that I pointed to a file I had no access to read.
401.3 Error message – Unauthorized due to ACL on resource
401.2 Error message – Logon failed due to server configuration
Note: Check out http://support.microsoft.com/kb/943891 for all the status codes in IIS7
The difference here is that on the WebRequest, it wasn’t even getting an NTLM token from the .Net app. This lead me astray however and made me think that there was a problem with the pre-authentication of the credentials as well as whether I was missing something in the web.config, or even if it was some unique problem with Sharepoint. After a lot of investigation I discovered the Microsoft KB article titled: “You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or IIS 6” After giving a thorough read of that document I realized the problem, Microsoft forgot to update the title of the KB article. The sub status code I was getting on the 401 errors is different than Microsoft mentions in the article, and while they don’t mention IIS 7 in the article’s title, it does show up in the applies to section.
Since Microsoft recommends you leave the loopback check in place because it is part of the security update, I followed their recommended method of adding in a specified host name to the BackConnectionHostNames key in the registry.
As always, make registry modifications at your own risk, Microsoft always recommends you make a backup before making any modifications, check out the following KB article for backup instructions: http://support.microsoft.com/kb/322756
Warning Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. These problems might require that you reinstall the operating system. TinyInt.Com cannot guarantee that these problems can be solved. Modify the registry at your own risk.
To specify the host names that are mapped to the loopback address and can connect to Web sites on your computer, follow these steps:
- Click Start, click Run, type regedit, and then click OK.
- In Registry Editor, locate and then click the following registry key:
- Right-click MSV1_0, point to New, and then click Multi-String Value.
- Type BackConnectionHostNames, and then press ENTER.
- Right-click BackConnectionHostNames, and then click Modify.
- In the Value data box, type the host name or the host names for the sites that are on the local computer, and then click OK.
- Quit Registry Editor, and then restart the IISAdmin service.
Now that you have taken care of editing the registry to include the hostname you are using in your code, you should be able to make your WebRequest over NTLM without a problem, just make sure you have impersonate=”true” in your web.config file.
Attached below is the code for the health check script that I have been talking about throughout this article. As I mentioned earlier, it does some very basic checks on the server just to see if things are running smoothly. To use it you would simply need to change the variables being passed into the various functions to check your database connectivity. We use WhatsUp Gold to track the value of ALL_STATUS_OK to make sure things are working properly, and once one of the values fails it sends us an alert. Another thing to keep in mind is if you are using the WebRequest piece in this code, make sure you grant the user you are authenticating as access to the Sharepoint page you are checking. Lastly, if you use the code, make sure you read the comment in the web.config file about encrypting the settings so your password is not exposed, even if you are using a low privileged user account.
Download Source: Download sharepoint-contentscan.zip