What is HTTP Response Splitting? Ways to Exploit, Examples and Impact

Learn what HTTP Response Splitting is, how CRLF injection works, and how to prevent these web vulnerabilities to protect your applications.

What is HTTP Response Splitting? Ways to Exploit, Examples and Impact

HTTP Response Splitting is a sophisticated web security vulnerability that occurs when an application fails to properly sanitize user-supplied input before including it in an HTTP response header. By injecting specific control characters, an attacker can effectively "split" a single HTTP response into two separate responses. This allows them to control the second response, leading to a variety of attacks including Cross-Site Scripting (XSS), cache poisoning, and session hijacking. Understanding this vulnerability is essential for any cybersecurity professional looking to secure modern web infrastructure.

Understanding the HTTP Protocol Structure

To grasp how HTTP Response Splitting works, we must first understand the underlying structure of the Hypertext Transfer Protocol (HTTP). HTTP is a text-based protocol. When a server sends a response to a client (like a web browser), that response follows a very specific format defined by the Internet Engineering Task Force (IETF).

A standard HTTP response looks like this:

HTTP/1.1 200 OK
Date: Mon, 23 Oct 2023 12:00:00 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Content-Length: 155
Connection: close

<html>
  <head><title>Success</title></head>
  <body><h1>Hello World!</h1></body>
</html>

In this structure, there are two critical components that act as delimiters:

  1. CR (Carriage Return): Represented as \r or hex code 0x0D.
  2. LF (Line Feed): Represented as \n or hex code 0x0A.

In the HTTP protocol, a single line is terminated by a CRLF sequence (\r\n). The headers are separated from the message body by a blank line, which consists of two consecutive CRLF sequences (\r\n\r\n). This predictable structure is exactly what an attacker exploits in a Response Splitting attack.

What is HTTP Response Splitting?

HTTP Response Splitting occurs when an application takes user input and places it into an HTTP response header without filtering out CRLF characters. If an attacker can inject %0d%0a (the URL-encoded version of CRLF), they can terminate the current header, start new headers, or even terminate the entire header section to begin a new, malicious HTTP response.

This vulnerability is often categorized as a subset of CRLF Injection. While CRLF injection refers to the act of injecting these characters, "Response Splitting" specifically refers to the outcome where the stream of data is interpreted as two distinct responses instead of one.

How the Attack Works: Technical Mechanism

Consider a web application that redirects users to a specific page based on a lang parameter. The server-side code might look something like this (in a vulnerable implementation):

<?php
  $lang = $_GET['lang'];
  header("Location: /index.php?lang=$lang");
?>

Under normal circumstances, a request to page.php?lang=en results in the following response:

HTTP/1.1 302 Found
Location: /index.php?lang=en

However, an attacker can craft a malicious payload. If they send a request with a payload containing CRLF characters, they can manipulate the response. For example:

page.php?lang=foobar%0d%0aContent-Length: 0%0d%0a%0d%0aHTTP/1.1 200 OK%0d%0aContent-Type: text/html%0d%0aContent-Length: 19%0d%0a%0d%0a<html>Split!</html>

The server, unaware of the injection, constructs the following response:

HTTP/1.1 302 Found
Location: /index.php?lang=foobar
Content-Length: 0

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 19

<html>Split!</html>

To the client (or an intermediary proxy), this looks like two separate HTTP responses. The first is a redirect with no body, and the second is a successful 200 OK response containing the attacker's HTML. This is the core of the exploit.

Common Exploitation Scenarios

HTTP Response Splitting is a "gateway" vulnerability. By itself, it allows for protocol manipulation, but its real danger lies in what the attacker does with that second, controlled response.

1. Cross-Site Scripting (XSS)

By splitting the response, an attacker can inject a second response that contains malicious JavaScript. Since the second response appears to come from the legitimate server, the browser will execute the script within the context of that domain's origin. This bypasses many traditional XSS filters because the script isn't in the first response's body, but in what the browser perceives as a subsequent response.

2. Web Cache Poisoning

This is perhaps the most dangerous application of Response Splitting. Many corporate networks and Content Delivery Networks (CDNs) use proxy servers to cache responses to improve performance. If an attacker sends a split response through a proxy, the proxy might associate the attacker's malicious second response with a legitimate URL requested by a subsequent user.

For example, if the proxy sees two responses but only one request from the attacker, it might become "desynchronized." The next user who requests a common file (like script.js) might be served the attacker's cached second response instead of the real file. This allows for large-scale exploitation of an entire user base.

3. Cross-User Defacement

Similar to cache poisoning, an attacker can use response splitting to deface a website for other users. By poisoning the cache with a response that contains a defaced version of the home page, every visitor using that cache will see the attacker's content.

Attackers can use response splitting to inject Set-Cookie headers into the response. This can be used to perform "Session Fixation" attacks, where the attacker sets a user's session ID to a known value, allowing the attacker to hijack the account once the user logs in. They can also overwrite security cookies like CSRF-Tokens or Secure flags.

Practical Examples of Payloads

To identify and test for this vulnerability, security researchers use various payloads designed to trigger visible changes in the HTTP stream.

Example 1: Basic Header Injection

Testing if you can add a simple header like X-Injected: True.
Payload: %0d%0aX-Injected: True
Resulting Header:

Location: /index.php?lang=en
X-Injected: True

Example 2: Forcing a Second Response (The Split)

Payload: %0d%0aContent-Length: 0%0d%0a%0d%0aHTTP/1.1 200 OK%0d%0aContent-Type: text/html%0d%0aContent-Length: 25%0d%0a%0d%0a<h1>You are hacked</h1>
This payload terminates the first response immediately and starts a new one with a custom HTML body.

Example 3: Bypassing Simple Filters

Sometimes developers try to filter \r and \n but forget about URL encoding or double encoding.
Payload: %250d%250a (Double encoded CRLF)
Payload: \u000d\u000a (Unicode representation)

Real-World Impact

The impact of HTTP Response Splitting can be catastrophic for an organization. Because it facilitates cache poisoning, a single successful exploit can compromise thousands of users simultaneously.

  • Data Theft: Through XSS, attackers can steal session cookies, personal information, and login credentials.
  • Reputational Damage: Website defacement or the distribution of malware via poisoned caches can destroy user trust.
  • Financial Loss: For e-commerce platforms, session hijacking can lead to unauthorized transactions and loss of revenue.
  • Compliance Violations: Failing to protect against well-known vulnerabilities like CRLF injection can lead to non-compliance with standards like PCI-DSS or GDPR.

How to Detect HTTP Response Splitting

Detecting this vulnerability requires looking for places where user input is reflected in headers. Common targets include:

  • Redirects (Location header)
  • Cookie setting (Set-Cookie header)
  • Custom metadata headers (X-Frame-Options, etc.)

Manual Testing

Using a tool like Burp Suite, a tester can intercept a request and manually inject %0d%0a into parameters. By observing the "Raw" response in the Repeater tab, the tester can see if the injected characters are interpreted as new lines or if they are properly encoded/stripped by the server.

Automated Scanning

Automated vulnerability scanners look for reflected input in headers and attempt to inject various CRLF sequences. However, these scanners sometimes miss complex cases where encoding is required. This is where continuous infrastructure monitoring comes into play. Tools like Jsmon help by providing visibility into your external attack surface, ensuring you know exactly where your applications are exposed.

How to Prevent HTTP Response Splitting

Prevention is primarily centered on strict input validation and the use of modern development frameworks that handle header generation securely.

1. Sanitize and Validate Input

Always treat user input as untrusted. If you are expecting a language code (like 'en' or 'fr'), validate the input against an allowlist. Do not allow characters like \r or \n in any input that will be used in a header.

2. Use Modern APIs and Frameworks

Most modern web frameworks (like Django, Ruby on Rails, or Express.js) and language-specific APIs (like modern Java Servlets) have built-in protections against CRLF injection. They will either throw an error or automatically strip/encode CRLF characters when you use their built-in header-setting functions. Avoid using raw print or echo statements to construct HTTP responses manually.

3. URL Encode Output

If you must reflect user input in a header, ensure it is properly URL-encoded. Since URL encoding turns \r\n into %0D%0A, the browser and intermediate proxies will treat them as literal text within a single header rather than protocol control characters.

4. Update Legacy Systems

HTTP Response Splitting was much more common in the early 2000s. Many older versions of web servers and application servers (like older versions of PHP or Tomcat) were vulnerable by default. Ensuring your stack is up to date is a critical defense-in-depth measure.

5. Deploy a Web Application Firewall (WAF)

A WAF can be configured to detect and block requests containing CRLF sequences in URL parameters or body data. While not a replacement for secure coding, it provides an important layer of protection.

Conclusion

HTTP Response Splitting is a classic example of how a simple oversight in input validation can lead to complex, multi-stage attacks. By manipulating the very fabric of the HTTP protocol, attackers can bypass security controls and compromise users at scale. While modern frameworks have made this vulnerability less common, it remains a significant threat in legacy systems, custom-built applications, and misconfigured environments.

By following secure coding practices, validating all inputs, and maintaining a clear view of your infrastructure, you can effectively defend against these attacks. Staying vigilant and using the right tools is the key to maintaining a robust security posture.

To proactively monitor your organization's external attack surface and catch exposures like CRLF injection before attackers do, try Jsmon.