Understanding HTTP Response Splitting

1. What is HTTP Response Splitting?

HTTP Response Splitting occurs when an attacker can inject special characters (such as CR and LF characters, represented as %0D%0A in URL encoding) into HTTP headers returned by the web application. These characters can create new, unexpected headers or even an entirely new HTTP response, allowing the attacker to manipulate how browsers or proxies interpret the response.

2. How HTTP Responses Work

An HTTP response typically looks like this:

HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: session=12345
Cache-Control: no-cache

<!DOCTYPE html>
<html>...
        

Each response contains:

3. The Attack Mechanism

  1. The attacker injects CR (%0D) and LF (%0A) characters into a user-controlled input that is reflected in an HTTP header
  2. These characters are interpreted as line breaks by the server, web proxies, and browsers
  3. This allows the attacker to terminate the current header and inject new ones
  4. The attacker can even inject a blank line followed by content to create a completely new response
User Input with
Malicious CR+LF
Server Uses Input
in HTTP Header
Browser/Proxy
Interprets CR+LF
Multiple HTTP Headers
or Responses

Setting Up the Demo Environment

To effectively demonstrate HTTP Response Splitting, you would need:

  1. Web Server: Apache, Nginx, or Node.js application
  2. Caching Proxy: Such as Squid or Varnish (for cache poisoning demonstrations)
  3. Database: For storing user preferences or profile information

For this demo, we'll simulate the server behavior using client-side JavaScript to show what would happen.

Note: Modern web frameworks and servers implement controls that make HTTP Response Splitting difficult, but understanding the vulnerability remains important.

HTTP Response Splitting Demonstrations

Redirect Location Header Injection

This demo shows how an attacker can inject new headers through the Location header in a redirect response.

Generated HTTP Response:

HTTP/1.1 302 Found Location: home.html Server: Demo/1.0 Date: Sun, 24 Mar 2024 12:00:00 GMT

Browser Interpretation:

The browser would redirect to: home.html

Attack Vectors:

Try these malicious inputs in the redirect field:

  • home.html%0D%0ASet-Cookie:%20stolen=yes - Injects a cookie
  • home.html%0D%0AContent-Type:%20text/html%0D%0A%0D%0A<script>alert('XSS')</script> - Creates a completely new response with XSS

In a vulnerable application, the server might construct a redirect header like this:


// VULNERABLE PHP CODE
$page = $_GET['page'];
header("Location: " . $page);
                    

If the attacker provides page=home.html%0D%0ASet-Cookie:%20stolen=yes, the server would send:


Location: home.html
Set-Cookie: stolen=yes
                    

HTTP Response Splitting for Cache Poisoning

This demo shows how HTTP Response Splitting can lead to cache poisoning attacks, where a malicious response is cached and served to multiple users.

Generated HTTP Request & Response:

GET /product?id=12345 HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Accept: text/html
HTTP/1.1 200 OK Content-Type: text/html Cache-Control: public, max-age=3600 ETag: "12345-abcdef" Vary: Accept-Encoding

Caching Proxy Behavior:

The proxy would cache this response for all users requesting product 12345

How Cache Poisoning Works:

  1. Attacker requests a resource with malicious input that exploits HTTP Response Splitting
  2. The server constructs a response with the injected headers/content
  3. A proxy cache between the server and users interprets this as multiple responses
  4. The proxy caches the second (fake) response
  5. All subsequent users requesting the same resource receive the attacker's content

For example, using this payload:

12345%0D%0AContent-Length:%200%0D%0A%0D%0AHTTP/1.1%20200%20OK%0D%0AContent-Type:%20text/html%0D%0ALast-Modified:%20Mon,%2027%20Oct%202008%2014:50:18%20GMT%0D%0AContent-Length:%2035%0D%0A%0D%0A<script>alert('Cache%20Poisoned')</script>

This would create an initial empty response followed by a completely new response that would be cached and served to all users.

Preventing HTTP Response Splitting

This tab demonstrates various techniques to prevent HTTP Response Splitting vulnerabilities.

Original Input:

test%0D%0ASet-Cookie:%20malicious=1

After Prevention:

Resulting HTTP Response:

HTTP/1.1 200 OK Content-Type: text/html Set-Cookie: preference=test%0D%0ASet-Cookie:%20malicious=1 Server: Demo/1.0

Effective Prevention Strategies:

1. Input Validation

// Validate input allows only expected characters
function validateRedirectUrl($url) {
    if (preg_match('/^[a-zA-Z0-9\/_.-]+$/', $url)) {
        return $url;
    }
    return 'default.html'; // Default safe value
}

$page = validateRedirectUrl($_GET['page']);
header("Location: " . $page);
                    
2. Output Encoding

// Encode CR and LF characters
function encodeHeaderValue($value) {
    return str_replace(["\r", "\n", "%0D", "%0A", "%0d", "%0a"], '', $value);
}

$lang = encodeHeaderValue($_GET['lang']);
header("Set-Cookie: language=" . $lang);
                    
3. Using Framework Safeguards

// Modern PHP using a framework's cookie API
// Laravel example
return redirect()->route('home')
    ->cookie('language', $request->input('lang'), 60);

// Node.js Express example
res.cookie('language', req.query.lang).redirect('/home');
                    
4. HTTP Response Headers

// Add security headers that disable caching for sensitive pages
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");
header("Expires: 0");
                    
5. Library Usage

// Use established libraries for URL manipulations
$page = filter_input(INPUT_GET, 'page', FILTER_SANITIZE_URL);
header("Location: " . $page);

// Java example
String sanitizedValue = Encode.forUriComponent(request.getParameter("page"));
response.sendRedirect(sanitizedValue);
                    

Summary: Preventing HTTP Response Splitting

1. Use Framework Abstractions

Modern web frameworks provide safe methods for setting headers and cookies:

2. Sanitize and Validate Input

Always validate and sanitize user input before using it in headers:

// PHP example
$page = preg_replace('/[\r\n]/', '', $_GET['page']);
header("Location: " . $page);

// JavaScript example
const userInput = userValue.replace(/[\r\n]/g, '');
response.setHeader("X-User-Input", userInput);
        

3. Use Content Security Policy

Implement Content Security Policy headers to mitigate the impact of successful attacks:

Content-Security-Policy: default-src 'self'; script-src 'self';
        

4. Keep Software Updated

Modern web servers and application frameworks have built-in protections against HTTP Response Splitting. Always keep your software updated to benefit from these security improvements.

5. Security Testing

Regularly test your applications for HTTP Response Splitting vulnerabilities:

HTTP Response Splitting Vulnerability Demo ← Back to All Vulnerabilities

HTTP Response Splitting Vulnerability

HTTP Response Splitting is a web application vulnerability that allows an attacker to manipulate HTTP responses from a server by injecting unexpected headers or an entirely new response. This can lead to cache poisoning, cross-site scripting (XSS), and page defacement.