<<< Date Index >>>     <<< Thread Index >>>

Technical Note by Amit Klein: Detecting and Preventing HTTP Response Splitting and HTTP Request Smuggling Attacks at the TCP Le



  Technical Note: Detecting and Preventing HTTP Response Splitting 
         and HTTP Request Smuggling Attacks at the TCP Level


                      Amit Klein, August 2005


Introduction
============

This technical note describes a detection/prevention technique that 
works in many cases both with HTTP Response Splitting and with HTTP 
Request Smuggling. This technique makes use of implicit information 
found in the TCP stream, namely the segmentation into packets and 
the TCP PSH bit. In HTTP Response Splitting, this technique needs 
to be applied at the proxy server, the one closest to the web 
server, and to the response stream. In HTTP Request Smuggling, this 
technique needs to be applied at the entity closest to the attacked 
proxy server/device (i.e. implemented in another proxy server, or 
the web server itself), and to the request stream (note, however, 
that this second server may be off the premises of the organization 
wherein the web server is, see also "Can HTTP Request Smuggling be 
blocked by Web Application Firewalls?", 
http://www.securityfocus.com/archive/107/402974).
 

TCP PSH bit and PUSH flag
=========================

Before describing the technique, the reader is reminded what are 
the TCP PSH bit and PUSH flag. RFC 793 (Transmission Control 
Protocol, http://www.ietf.org/rfc/rfc793.txt) defines the push 
functionality as following (from section 1.5):

      Sometimes users need to be sure that all the data they have
      submitted to the TCP has been transmitted.  For this purpose 
      a push function is defined.  To assure that data submitted to 
      a TCP is actually transmitted the sending user indicates that 
      it should be pushed through to the receiving user.  A push 
      causes the TCPs to promptly forward and deliver data up to 
      that point to the receiver.

And in section 2.8:

      The sending user indicates in each SEND call whether the data 
      in that call (and any preceeding [sic] calls) should be 
      immediately pushed through to the receiving user by the 
      setting of the PUSH flag.

This is realized by a PSH bit in the TCP header.

RFC 793 also mandates that the socket API provides means for the 
caller to set this bit via a PUSH flag in the SEND function, and to 
likewise receive it in the RECV function. 
However, this requirement was later waived in RFC 1122 
(Requirements for Internet Hosts - Communication Layers, 
http://www.ietf.org/rfc/rfc1122.txt), section 4.2.2.2:

      A TCP MAY implement PUSH flags on SEND calls. If PUSH flags 
      are not implemented, then the sending TCP: (1) must not 
      buffer data indefinitely, and (2) MUST set the PSH bit in the 
      last buffered segment (i.e., when there is no more queued 
      data to be sent).

      The discussion in RFC-793 on pages 48, 50, and 74 erroneously 
      implies that a received PSH flag must be passed to the 
      application layer. Passing a received PSH flag to the 
      application layer is now OPTIONAL.

And indeed, the two implementations of sockets, the UNIX BSD 
sockets and WinSock, do not implement the PUSH flag neither in SEND 
nor in RECEIVE:

*) FreeBSD (example of standard BSD sockets)
   send(2) man page:   
http://www.freebsd.org/cgi/man.cgi?query=send&apropos=0&sektion=2&manpath=FreeBSD+5.4-
RELEASE+and+Ports&format=html
   recv(2) man page: 
http://www.freebsd.org/cgi/man.cgi?query=recv&apropos=0&sektion=2&manpath=FreeBSD+5.4-
RELEASE+and+Ports&format=html

*) Sun Solaris 8 (another example of standard BSD sockets)
   send(3SOCKET) man page: 
http://docs.sun.com/app/docs/doc/806-0628/6j9vie803?a=view 
   recv(3SOCKET) man page: 
http://docs.sun.com/app/docs/doc/806-0628/6j9vie7u0?a=view 

*) Microsoft Windows WinSock (2.0) sockets: 
   send:    
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/send_2.asp
   recv: 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/recv_2.asp
 

This means that according to RFC 1122, these implementations should 
simply set the TCP PSH flag in the last TCP segment of the caller's 
data buffer. Unfortunately, this also means that socket 
applications do not have direct access to the PSH bit (in other 
words, it would take some hacking around the standard sockets API 
to get this information - thus making the whole idea presented 
below much harder to implement in pure sockets applications).
To illustrate: a sender uses the sockets send() function to send a 
payload of 2000 bytes over a TCP circuit on a LAN. The call is 
(assuming C API):

      send(socket, buffer, 2000, ...);

This results in 2 TCP segments (IP packets), the first carrying a 
payload of 1448 bytes (maximal LAN packet, minus level 2, IP and 
TCP headers), the second carrying a payload of the remaining 552 
bytes, with a PSH bit set.
In contrast, having the caller invoke send twice to send the same 
data:

      send(socket, buffer, 1000, ...);
      send(socket,buffer+1000, 1000, ...);

Results in 2 TCP segments, both having 1000 bytes of payload, and 
both having the PSH bit set.
Therefore, by inspecting the TCP header, one can figure out (in 
this rather simplistic example) whether the data was sent via a 
single call to send(), or via two calls.
This observation is the basis for the following technique described 
below.
 

Detecting HTTP Response Splitting and HTTP Request Smuggling
============================================================

Detection of HTTP Response Splitting attack can be realized by 
fulfilling the following requirements (the technique can be applied 
to HTTP Request Smuggling with some obvious modifications):

Requirement #1: Deny "pipelined" traffic, that is, do not accept a 
second response before a first response was fully served, and a 
second request was fully received. Particularly, a packet 
containing data for the first response must not contain superfluous 
data beyond the end of the first response (i.e. a second response).

Requirement #2: Since from #1 it follows that the end of the first 
response coincides with an end of a packet, and end of 
transmission, such packet should contain a PSH bit set (see above).

Requirement #1 is obvious, yet insufficient, as shown in the 
successful HTTP Response Splitting attacks against Squid and 
NetCache (see "Divide and Conquer - HTTP Response Splitting, Web 
Cache Poisoning Attacks, and Related Topics", 
http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf, 
pp. 15-19), although both products impose packet 
boundary requirements (making sure that the first response 
terminates at a packet boundary isn't so hard if the packet length 
is known to the attacker). But if we are to add requirement #2, the 
attack can be thwarted in many cases, because the attacker has no 
way of forcing the web server to send the PSH flag (remember that 
the from the web server's perspective, it is in the middle of the 
first response, and will send the PSH bit only at the end of the 
first response). Of course, it may be possible that the web server 
always sends the PSH bit (for example, the TCP stack of IBM TPF 4.1 
apparently does so by default - see the description of TCP_PSH_LAST 
ioctl option in http://www-306.ibm.com/software/htp/tpf/serv/GTPMLB19.pdf), 
or sends it after each HTTP response header, or in the middle of 
the response, but that is not the case with many servers (although
I have seen servers that on occasion will send the PSH flag in the
middle of HTTP responses).

So, while it may not be perfect, it seems that this technique has a 
high detection probability (much higher than enforcing requirement 
#1 alone), yet very low likelihood for false positives. 


Notes
=====

1. The technique fails if there are TCP/HTTP aware devices between 
the web server and the proxy server, as these may alter the TCP 
stream.

2. The technique can be applied to HTTP Request Smuggling as 
following: the proxy server forwards the requests to the web 
server. The web server (or the receiving entity) needs to verify 
that the request ends on a packet boundary, and that the PSH flag 
is set.

3. While the technique covers detection of attacks, since such 
detection is carried out in real-time, it is possible to terminate 
the TCP connection (or perform other actions) and thereby to block 
the attack. 

4. This technique lends itself nicely to detection/prevention by 
network IDS/IPS, as it only requires sniffing the TCP/IP traffic 
and flagging HTTP requests/responses that do not terminate on a 
packet boundary, with PSH bit set.


Alternatives
============

Other, complementary methods (for prevention) that are known to 
work are:

1. The web site can use SSL connections (HTTPS) only. This will 
only eliminate 3rd party proxy servers. It does not eliminate the 
browser cache issue, and it may not handle the site's own cache 
server (or any other on-site HTTP aware devices). Of course, 
migrating to SSL only has many real-life drawbacks.

2. A proxy cache server can be configured not to use persistent 
HTTP connections with the *server*, in which case, its cache will 
not be poisoned. This prevention technique has significant 
performance impact.


Summary
=======

Observing that an end of HTTP request/response message is aligned 
with a TCP segment (packet) boundary, *and* that that segment has 
the PSH bit set, can be an effective way to detect and prevent HTTP 
Response Splitting and HTTP Request Smuggling. This technique can 
be easily employed when the TCP layer is directly accessible (as 
opposed to the sockets model). 


Off topic personal notice/clarification
=======================================

I am often asked whether I work for Watchfire, or did so in the 
past. So let me state the following:

1. I am not employed by Watchfire, and I am not part of any 
Watchfire team.

2. In fact, I have never been employed by watchfire (I was employed 
by Sanctum for many years, but I quit Sanctum slightly before it 
was acquired by Watchfire).

Having said that, I have nothing against Watchfire, and I wish them 
best of luck.