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