What is HTTP response splitting?

18

Reading about HTTP headers I came across a filter function that removed both invalid characters from the header field value and multiple CRLF characters. This second on the pretext of avoiding the HTTP response splitting . By what I understand superficially, this attack consists of you defining the value of the field containing at least two CRLF and thus having full control of the body of the request.

For example:

Fake: foo\r\n\r\nHello world

This header field would be interpreted as:

Fake: foo

Hello world

Where, then, Hello world would be interpreted as the body of the request because of the blank line separating the headers from the content, see HTTP specification. Or rather, if the HTTP response has something like:

HTTP/1.1 200 OK
Fake: foo\r\n\r\nHTTP/1.1 200 OK\r\n\r\nHello World

It will be interpreted as:

HTTP/1.1 200 OK
Fake: foo

HTTP/1.1 200 OK

Hello World

That is, two distinct HTTP responses, which define the name response splitting .

  • HTTP response splitting is that right or misunderstood?
  • What are the risks for the application not to treat this vulnerability?
  • Servers such as Apache and Nginx already have some sort of security against this?

If possible, give examples of requests that use HTTP response splitting to take advantage of the server vulnerability.

    
asked by anonymous 06.07.2017 / 14:37

2 answers

3

According to OWASP , HTTP response splitting attack is a means to an end, not an end in itself even - that is, it is a breach used to perform other types of attacks. At its root, the attack is direct: an attacker passes malicious data to a vulnerable application and the application includes the data in an HTTP response header.

"HTTP response splitting" occurs when:

  • Data enters a Web application from an untrusted source, most often it is an HTTP request.
  • Data is included in an HTTP response header sent to a web user without being validated for malicious characters.

To mount a successful attack, the application must allow input that contains CR (carriage return, represented by %0d or \r ) and LF (line feed, represented by %0a or \n ) in the header and the underlying platform must be vulnerable to the injection of such characters. These characters not only give attackers control over the remaining headers and the response body that the application intends to send, but also allow them to create additional responses under their control.

I think this vulnerability has generally been fixed on most modern application servers, regardless of the language in which the code was written. At least on the pertinent issues I encountered in link (Stack Exchange Community facing security) almost all are necessarily an attack. But some have in common the fact that they use loopholes in proxy and not necessarily the web server itself, so it is still possible that these attacks occur nowadays.

If you are concerned about this risk you should test on your current platform if it allows CR or LF characters to be injected into headers. The example below uses an example Java, but this problem has been fixed on virtually all modern Java EE application servers. If you are concerned about this risk, you should test on the platform of concern to see if the underlying platform allows CR or LF characters to be injected into headers.

For a practical example we will take the requisition:

 HTTP/1.1 200 OK
 Date: Thu, 13 Jul 2017 02:02:45 GMT
 Last-Modified:Mon, 10 Jul 2017 21:30:06 GMT
 Accept-Ranges:  none
 Connection: close
 Content-Type: text/html; charset=UTF-8
 Cookie: test=114&username=João

 <html>
 [...]

However, since the cookie value is formed from unvalidated user input I can change my user name 'John' and include CRLF (as I explained above) in the field. An attacker could then inject malicious content into the page, for example, it would be possible to set username to 'John \ r \ n \ r \ ncontent malicious ...', which would result in the following HTTP response:

 HTTP/1.1 200 OK
 Date: Thu, 13 Jul 2017 02:02:45 GMT
 Last-Modified:Mon, 10 Jul 2017 21:30:06 GMT
 Accept-Ranges:  none
 Connection: close
 Content-Type: text/html; charset=UTF-8
 Cookie: test=114&username=João

 <script>conteúdo malicioso ... </script>
 <html>
 ...

In this example JavaScript code was injected into the page. This is a form of XSS / DOM injection through the splitting attack but not necessarily a HTTP response splitting , but uses the same technique to inject some malicious code into the page.

Now let's for example change the malicious code to something like "John \ r \ n \ r \ nContent-Length: 45 \ r \ n \ r \ nnasty content ...", the HTTP response would be divided into a response imposter followed by the original response, which is now ignored:

 HTTP/1.1 200 OK
 Date: Thu, 13 Jul 2017 02:02:45 GMT
 Last-Modified:Mon, 10 Jul 2017 21:30:06 GMT
 Accept-Ranges:  none
 Connection: close
 Content-Type: text/html; charset=UTF-8
 Cookie: test=114&username=João
 Content-Length: 45

 <html>conteúdo malicioso ... </html>
 <html>conteúdo original começa após o 46º caracter e é ignorado.[...]

On an unprotected server you could send the CRLF characters through the querystring:

http://www.yoursite.com/somepage.php?page=%0d%0aContent-Type: text/html%0d%0aHTTP/1.1 200 OK%0d%0aContent-Type: text/html%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E

The client would see the result of the script, which in this case is a simple alert:

<script>alert(1)</script>    

If you make a test like this in your application, and you can see the alert, your system is vulnerable to CRLF injection, therefore vulnerable to HTTP response splitting .

The attacker's ability to construct HTTP responses using HTTP response splitting allows for several other resulting attacks, including: Cross-User Defacement , Cache Poisoning , # and Page Hijacking .

    
14.07.2017 / 14:51
2

You can not have two responses for a request. The name comes from the possibility of returning two contents in the same response - one false and the other true, but this second will be ignored.

Using the Wikipedia example HTTP Response Splitting :

If you make a request where the return is based on querystring , for example:

GET /consoto.com/author/Jane+Smith
HTTP/1.1 200 OK
...
Set-Cookie: author=Jane Smith
...

If you make the same request, with CR + LF injection:

GET /contoso.com/author/Jane+Smith\r\nContent-Length:45\r\n\r\n...
...
Set-Cookie: author=Jane Smith
Content-Length: 999

<html>conteúdo malicioso...</html> (até 999 caracteres neste exemplo)

The original response content will start from character 1000, which will be ignored by the browser.

Imagine that your application to display profile data for your user is something like /usuarios/Anderson+Woss , an attack would be to create a /usuario/Anderson+Woss+<um formulario pedindo dados bancários> URL and send it to thousands of emails. Using your domain and your credibility to gain illicit benefits.

There is no reason for web publishers if they "protect" this, as it is possible that this is a valid request for your application. It depends on your business.

To prevent this, there are HTTP Filters . This in any web technology. And there you can prevent this type of exploit.

    
10.07.2017 / 11:02