Share via


Challenge-Response Authentication and Zero-Length Posts

From time-to-time, web developers contact the IE team reporting that they’ve encountered a problem whereby Internet Explorer submits a POST but fails to transmit the content body. This bodyless POST indicates via the Content-Length header that the POST is zero-bytes long, regardless of how much data was supposed to be uploaded.

This behavior occurs on servers that use challenge-response authentication protocols like NTLM or Kerberos/Negotiate. For performance reasons, Internet Explorer does not immediately transmit a POST body if it expects to immediately receive a HTTP/401 response with a challenge for credentials. Without this optimization, IE would be forced to reupload the (potentially large) POST body multiple times, wasting bandwidth.

The obvious question: What leads IE to expect a credential challenge?

IE expects a credential challenge if it has previously received a credential challenge from within the protection space. Put simply, a protection space is the origin+current folder path and any paths beneath it.

Consider the following example:

  1. https://example.com/privateupload/ – upload private files, secured by a username/password
  2. https://example.com/privateupload/admin/ – upload admin files, secured by a username/password
  3. https://example.com/publicupload/ – upload public files

In this case, the first two folders challenge the client for a username and password, while the public folder does not.

After the first credential challenge from the privateupload folder, the next time the client submits a POST to that folder or the admin folder beneath it, the POST will be zero-bytes in length. If the server returns a 401 as expected, the client will respond to the challenge and eventually upload the entire POST-body. If, however, the server does not return a 401 response, the client will simply submit the single zero-byte post, which likely will lead to an error message or a corrupted file on the server.

In the configuration above, the user will encounter a problem if he submits a bodyless POST to /publicupload/; since no credential challenge will be forthcoming, the upload will fail.

What might unexpectedly trigger the bodyless POST optimization? Most common cases are due to server configuration errors. For instance, if the user visits https://example.com/privateupload (without the trailing slash), the server might mistakenly return a 401 first, instead of immediately returning a 301 to /privateupload/ . If this happens, the protection space will be considered to be the root folder https://example.com/\* , causing all POSTs to any path anywhere on the server to trigger the bodyless POST optimization.

A similar problem occurs when the user never directly visits a page within the root folder, but a page within a subfolder issued a request to the root that resulted in an authentication challenge. A common case is the download of FavIcon.ico, for instance.

To avoid problems with the bodyless POST optimization, ensure that either all paths are configured to require authentication, or that only very specific subpaths require credentials and that all files within the protection space are configured to require authentication.

Until next time,

-Eric

Comments

  • Anonymous
    November 26, 2010
    Hi Eric, Very informative. Thanks. Does .net implementation of HTTP protocol exhibits the same behavior? Because recently in our company proxy authentication mechanism has been changed. Upon investigation with fiddle(btw thaks for it) and wireshark, we determined that client is sending 0 length requests after the first request which are allowed to pass through the proxy. Because there is no content third party service is throwing exceptions. Could you suggest any work around? Thanks, Shiva

  • Anonymous
    December 02, 2010
    @shiva: I would not be surprised to learn that .NET's implementation behaves the same way for the same reason (also for performance). One simple way to check would be to configure Fiddler to do authentication for you instead of having the client do it. (See the comments about X-AutoAuth here blogs.msdn.com/.../using-reflection-to-get-ntlm-negotiate-challenge-response-string-without-sending-request-using-webrequest-object.aspx)

  • Anonymous
    October 15, 2012
    Hi Eric, We are also facing this issue  , our backend is in Java and we use sso (LDAP) based authentication, we face this issue intermittently for Ajax POST , Form Submit(POST) , kindly let us know if any solution . Thanks in advance, Lalit

  • Anonymous
    July 11, 2013
    Hi Eric, Not sure if you still respond to comments on this blog, but I had a question about IE "protection spaces".  You say they made up of the origin and current folder.  What do you mean by "origin" in this case?  The origin in IE's "same origin policy" does not include port.  However, in my testing with two IIS sites that differ only by port, I am unable to reproduce the zero-length post problem.  When all my content is in one IIS site (some using integrated authentication and some using forms authentication), I can reproduce the problem consistently. So, does "origin" in terms of IE protection spaces include the port? Thanks, Robert EricLaw [MSFT]: Robert: That's a very interesting finding. I wouldn't expect the port to matter in this case, but it's entirely possible that the comparison logic used down in WinINET is using the port rather than the Zone (since WinINET doesn't have much interaction / knowledge of URLMon's Origin rules). The fact that a request on a different port necessarily MUST be sent on a different connection may be relevant here.

  • Anonymous
    March 03, 2014
    hi, I have a problem with IE and NTLM authentication. The POST values are not coming in PHP. we did the following configurations as follows, AuthType NTLM
    NTLMAuth on
    NTLMAuthoritative on
    NTLMDomain ASCORP
    NTLMServer nav8adasnp04.ascorp.com
    NTLMBackup nav8adasnp03.ascorp.com [EricLaw] Have you actually watched what's coming over the network using Fiddler or Wireshark? Do you have a capture file you could send me?

  • Anonymous
    June 26, 2014
    So is Microsoft ever going to fix this?  Interestingly, we used to face this problem with IE6 three to four years ago, but as out organization migrated to IE8, the problem went away.  Now we are migrating to IE10, and the problem is back again. In our case, the issue manifests somewhat differently. If a page request after a NTLM negotiate returns client side artifacts, a subsequent POST request will contain an unsolicited NTLM response header.  IE includes the header and a Zero Content length header even though the browser was not solicited with a WWW-negotiate header from the server. [EricLaw] Sorry, you haven't provided enough details to help; claims like: "The request contains a response header" are very ambiguous. Please feel to contact me by email. Thanks!

  • Anonymous
    September 22, 2014
    If I perform sign on to my web application with a context root of "/myapplication", but the initial request that triggered an authentication challenge to the browser was submitted to a more qualified path "/myapplication/some/path", a subsequent request to retrieve a client side artifact from "/myapplication/some.js" will cause the next POST request to be a zero byte NTLM negotiate response.  Basically, IE incorrectly returns an NTLM negotiate response even though it was not solicited with a challenge request. From my testing, the reproduction of this bug is as follows: IE6 -> reproducible
    IE7,8 -> not reproducible
    IE10 -> reproducible
    Any non microsoft browser -> not reproducible [EricLaw] When you say "the next POST request"-- To where is the next POST targeted? If it's targeted to the protected path, then this is by design. If not, that would be a problem, but I'm not able to reproduce any such problem with Internet Explorer 11. Do you have a Fiddler .SAZ capture I can look at?