j0e of LearnSecurityOnline.com recently mentioned that he was actively looking for examples of ‘HTTP Response Splitting.’ I was aware of the vulnerability, but always considered it somewhat theoretical, and didn’t fully understand the concepts. OWASP has a good blurb on it, and this is how I had initially become aware of it.
After examining it closer, I discovered that the vulnerability is nothing more than a more powerful version of XSS. In this case, you’re allowed to inject to the response HEADERS as opposed to (simply) the BODY with XSS. Response Splitting is a more dangerous vulnerability because of this. It will allow you to take full control of the body, and depending on the injection point, set arbitrary values in the HTTP Response header.
How does the vulnerability work? Fundamentally, it’s just an untrusted input and un-encoded output problem (though you can be vulnerable to certain payloads even if you encode output). When unverified input is used to set a value in the HTTP Response Headers, the vulnerability can be used.
For instance, suppose there are 2 pages: http://www.0x0e.org/page1.php and http://www.0x0e.org/page2.php.
- First, a form value (lets call it ‘x’) from page1.php is passed to page2.php and accessed via $_POST[‘x’], $_REQUEST[‘x’], $HTTP_POST_VARS[‘x’], or $x (if register globals is on). If this value is used without verification, we have a problem.
- To make a HTTP Response Splitting vulnerability, x must be used to set a value in the HTTP Response. This can be done in PHP using the Header(“Arbitrary-Header-Example: $x) call.
Now, an attacker can use this to his advantage by placing input in the form variable x on page1.php which is passed to page2.php. This input might look something like:
Value of Arbitrary Header%0d%0A
<html><body> 0wned. </body></html>%0d%0A
which would be placed before the original (correct) response, be parsed by the victim’s browser, and displayed on their screen. The full HTTP response would look something like:
GET /page2.php HTTP/1.1
Host www.0x0e.org
User-Agent "SparkyBrowse 2.0"
Accept */*
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
Connection keep-alive
Referer http://www.0x0e.org
If-Modified-Since Thu, 21 Aug 2008 00:10:17 GMT
Cache-Control max-age=0
Arbitrary-Header-Example: Value of Arbitrary Header
<html><body> 0wned. </body></html>
--------------------------------------------------------------------------
[original page2.php body -- not processed by the browser]
--------------------------------------------------------------------------
<html>
<head> Page2.php </head>
<body> This is the original Page2.php </body></html>
Notice how the %0d%0A disappeared in the full response? It’s being processed by the webserver, and depending on the OS, the attacker must tailor the input (just LF on *nix, CRLF on win*)
The most important thing to take away from this: HTTP Response Splitting is a stronger form of XSS. Nothing More.