This attack may also be called a CRLF injection.
If an attacker manages to inject malicious data into the headers, they can trick the browser to think that it’s really in the body and not part of the headers. The browser will execute the body as HTML and as such, XSS becomes possible.
As old headers also become part of the body, so now, the attacker can access cookies previously protected by the HttpOnly flag.
What can happen?
This vulnerability can be used to execute XSS attacks and steal data in headers, such as cookies protected by the HttpOnly flag.
Example of HTTP Response Splitting
Let’s assume PHP is vulnerable to this, making the following code dangerous.
<?php // this won't work in reality as header() isn't vulnerable header("Set-Cookie: c=" . $_GET["c"] . ";"); header("Set-Coookie: s=" . $secret . "; HttpOnly"); echo "Welcome to this page!"; ?>
If we access https://example.com/index.php?c=hello the response is:
HTTP/1.1 200 OK Set-Cookie: c=hello; Set-Cookie: s=[secret token]; HttpOnly Connection: Keep-Alive Content-Type: text/html Welcome to this page!
If we access https://example.com/index.php?c=%0d%0aContent-Type: text/html%0d%0a%0d%0a<script>alert(1)</script> instead, the response would be:
HTTP/1.1 200 OK Set-Cookie: c= Content-Type: text/html <script>alert(1)</script>; Set-Cookie: s=[secret token]; HttpOnly Connection: Keep-Alive Content-Type: text/html Welcome to this page!
User input containing CR (Carriage Return) and LF (Line Feed) needs to get filtered accordingly. Some languages accept “\r” and “\n” as well, which may cause issues.
Be sure to filter this kind of language-specific identifiers and read up on what characters may cause issues in your language.