Description
The HTTP Request Smuggling attack explores an incomplete
parsing of the submitted data done by an intermediary http
system working as a proxy. The HTTP Request Smuggling
consists in sending a specially formatted http request that
will be parsed in different way by the proxy system and by
the final system, so the attacker could smuggle a request to
one system without the other being aware of it. This attack
makes it possible to exploit other attacks like: web cache
poisoning, session hijacking, cross-site scripting and most
importantly, the ability to bypass web application firewall
protection.
To exploit the HTTP Request Smuggling, it’s necessary to
exist some specific condition such as the presence of
specific proxy system and version such as SunOne Proxy 3.6
(SP4) or FW-1/FP4-R55W beta or yet a XSS vulnerability in
the web server.
Basically the attack consists in submitting an HTTP
request that encapsulates a second HTTP request in the same
header, as shown below.
GET /some_page.jsp?param1=value1¶m2=
Content-Type: application/x-www-form-
Content-Length: 0
Foobar: GET /mypage.jsp HTTP/1.0
Cookie: my_id=1234567
Authorization: Basic ugwerwguwygruwy
In this case the first HTTP header is parsed by the proxy
system and the second by the final system, as it’s possible
to observe the target URL is different from the first one
permitting this way to bypass the proxy’s access control.
The attack could be exploited in different ways as reported
by “HTTP Request Smuggling” paper by Watchfire, so it’s
possible to realize these attacks: • Web Cache Poisoning
• Firewall/IPS/IDS evasion
• Forward vs. backward HRS
• Request Hijacking
• Request Credential Hijacking
Below are two examples of the HTTP Request Smuggling
exploit.
Severity
High
Likelihood of exploitation
Medium
Examples
Example 1 - Cache Poisoning Exploiting
Our first example demonstrates a classic HRS attack.
Suppose a POST request contains two "Content-Length" headers
with conflicting values. Some servers (e.g., IIS and Apache)
reject such a request, but it turns out that others choose
to ignore the problematic header. Which of the two headers
is the problematic one? Fortunately for the attacker,
different servers choose different answers. For example,
SunONE W/S 6.1 (SP1) uses the first "Content-Length" header,
while SunONE Proxy 3.6 (SP4) takes the second header (notice
that both applications are from the SunONE family). Let SITE
be the DNS name of the SunONE W/S behind the SunONE Proxy.
Suppose that "/poison.html" is a static (cacheable) HTML
page on the W/S. Here's the HRS attack that exploits the
inconsistency between the two servers:
1 POST http://SITE/foobar.html HTTP/1.1
2 Host: SITE
3 Connection: Keep-Alive
4 Content-Type: application/x-www-form-urlencoded
5 Content-Length: 0
6 Content-Length: 44
7 [CRLF]
8 GET /poison.html HTTP/1.1
9 Host: SITE
10 Bla: [space after the "Bla:", but no CRLF]
11 GET http://SITE/page_to_poison.html HTTP/1.1
12 Host: SITE
13 Connection: Keep-Alive
14 [CRLF]
[Note that each line terminates with a CRLF ("\r\n"),
except for line 10.] Let's examine what happens when this
request is sent to the W/S via the proxy server. First, the
proxy parses the POST request in lines 1-7 (in blue), and
encounters the two "Content-Length" headers. As we mentioned
earlier, it decides to ignore the first header, so it
assumes the request has a body of length 44 bytes.
Therefore, it treats the data in lines 8-10 as the first
request body (lines 8-10, in purple, contain exactly 44
bytes). The proxy then parses lines 11-14 (in red), which
treats as the client's second request. Now let's see how the
W/S interprets the same payload, once it has been forwarded
to it by the proxy. Unlike the proxy, the W/S uses the first
"Content-Length" header: as far as it's concerned, the first
POST request has no body, and the second request is the GET
in line 8 (notice that the GET in line 11 is parsed by the
W/S as the value of the "Bla" header in line 10). To
summarize, this is how the data is partitioned by the two
servers:
1st request 2nd request
SunONE Proxy lines 1-10 lines 11-14
SunONE W/S lines 1-7 lines 8-14
Next, let's see which responses are sent back to the
client. The requests the W/S sees are "POST /foobar.html"
(from line 1) and "GET /poison.html" (from line 8), so it
sends back two responses with the contents of the "foobar.html"
page and the "poison.html" page, respectively. The proxy
matches these responses to the two requests it thinks were
sent by the client - "POST /foobar.html" (line 1) and "GET /page_to_poison.html"
(line 11). Since the response is cacheable (we assumed "poison.html"
is a cacheable page), the proxy caches the contents of "poison.html"
under the URL "page_to_poison.html", and voila: the cache is
poisoned! Any client requesting "page_to_poison.html" from
the proxy would receive the "poison.html" page. A technical
note: Lines 1-10 and 11-14 have to be sent in two separate
packets, since SunONE Proxy doesn't pipeline requests on the
same packet.
Example 2 - REQUEST CREDENTIAL HIJACKING
Another area of interest is the ability of the attacker
to forcefully invoke a script (/some_page.jsp) with a client
credentials. This attack is similar in effect to the
Cross-Site Request Forgery attack [6], yet it is more
powerful because the attacker is not required to interact
with the client (victim). The attack is as follows:
POST /some_script.jsp HTTP/1.0
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
Content-Length: 142
this=thatGET /some_page.jsp?param1=value1¶m2=value2 HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Foobar:
When the client sends a request, such as:
GET /mypage.jsp HTTP/1.0
Cookie: my_id=1234567
Authorization: Basic ugwerwguwygruwy
Tomcat will glue this to the queued incomplete request,
and together, it will have:
GET /some_page.jsp?param1=value1¶m2=value2 HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Foobar: GET /mypage.jsp HTTP/1.0
Cookie: my_id=1234567
Authorization: Basic ugwerwguwygruwy
Now a complete request, it will invoke the script /some_page.jsp
and return its results to the client. If this script is a
password change request, or a money transfer to the
attacker's account, then this may potentially incur serious
damage to the client.
References