[WEB SECURITY] HTTP Request Smuggling - ERRATA (the IIS 48K buffer phenomenon)

Amit Klein (AKsecurity) aksecurity at hotpop.com
Thu Sep 22 07:41:40 EDT 2005


Hi 

With respect to the IIS/5.0 48K "bug" (see "HTTP Request Smuggling", 
http://www.watchfire.com/resources/HTTP-Request-Smuggling.pdf, pages 6-7
or 4-5),
Noam Ben-Yochanan commented that IIS/5.x provides with the programmer with
a way to consume
the request body (beyond the 48K usually read), thus disabling the HTTP
Request Smuggling
caused by this anomaly. Noam sent me a link that explains this:

Microsoft Knowledge Base article #810957:
http://support.microsoft.com/default.aspx?scid=kb;en-us;810957

The short story is that IIS reads the body in buffers of 48KB (the
default
value of UploadReadAheadSize in the MetaBase registry). It probably always
reads
the first buffer. 
Now, the HTTP Request Smuggling trick works by sending any Content-Type
OTHER THAN application/x-www-form-urlencoded. This means that IIS has
nobody parsing
the data and consuming more data, so it stops reading after those 48K, and
whatever
comes next is considered the next request (while MS says it is "by
design", in my
opinion this is still a bug, and with security implications).

As Noam noted, it is possible to "artificially" consume the data using
Request.BinaryRead, e.g. something like:

  Dim data
  data = Request.BinaryRead(Request.TotalBytes) 

And by this, restore order.

So a possible solution is to insert the above code in every ASP page.

However, there is a serious downside to this method: if a page accesses
Request.BinaryRead, it cannot access the Form collection (see the
documentation of 
BinaryRead in 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/ht
ml/c84b1f88-1a8a-
4370-95de-e907f7fdd5e7.asp).

Here's an improved solution. Note that the Content-Type of the request
must be anything other than application/x-www-form-urlencoded for the
attack to work (I
understand now that this is due to the fact that in
application/x-www-form-urlencoded, the 
IIS ASP.dll consumes the request body in fullness). So if a script wants
to secure itself, 
it should check whether the Content-Type (accessible via 
ServerVariables("HTTP_CONTENT_TYPE") is
application/x-www-form-urlencoded.
If it is, then the script can proceed as usual, and access the data
through the 
Request.Form collection. If the Content-Type is not
"application/x-www-form-urlencoded", then the script 
should consume the data (as in the above example), and log the event
(since this is probably an attack). Ideally, the script would terminate
the TCP
connection, but I don't know whether a script can terminate the TCP
connection in a
reliable manner. 
Perhaps sending a "Connection: Close" header can do the trick (or a 400
status code?). 

So the proposed solution would be something like (pardon me for any ASP
syntax error):

If (Request.ServerVariables("HTTP_CONTENT_TYPE") <> _
"application/x-www-form-urlencoded") Then
	' Log a security error condition
	' Consume leftover data
	Dim data
	data = Request.BinaryRead(Request.TotalBytes) 
	' Exit gracefully - do not proceed to normal flow
EndIf
' Work as usual, can access Request.Form

Still, it requires every ASP page to embed this kind of code. I think
this
makes the solution infeasible. And frankly I still call this a bug (be it
by design or
not) - an ASP page should not worry about its content-type or consuming
the request body.

Thanks again to Noam!
-Amit




---------------------------------------------------------------------
The Web Security Mailing List
http://www.webappsec.org/lists/websecurity/

The Web Security Mailing List Archives
http://www.webappsec.org/lists/websecurity/archive/



More information about the websecurity mailing list