Skip to main content
Offensive360
Home / Knowledge Base / HTTP Response Splitting
High CWE-113 A03:2021 Injection

HTTP Response Splitting

HTTP response splitting injects CRLF sequences into HTTP headers, allowing attackers to craft malicious responses, conduct cache poisoning, and perform cross-site scripting attacks.

Affects: JavaPHPPythonC#JavaScriptRuby

What is HTTP Response Splitting?

HTTP Response Splitting (CRLF Injection) occurs when user-supplied data containing carriage return (\r, CR) and line feed (\n, LF) characters is included in an HTTP response header without sanitization. Since HTTP headers are separated by \r\n sequences, injecting these characters allows an attacker to insert arbitrary headers or — by injecting a double CRLF — create an entirely new response body.

Consequences include: session cookie hijacking via injected Set-Cookie headers, cross-site scripting by injecting a new HTML body, cache poisoning that causes proxy servers to serve attacker-controlled content to other users, and open redirect via injected Location headers.

How exploitation works

An application sets a redirect header using user input:

GET /redirect?url=https://example.com HTTP/1.1

An attacker URL-encodes CRLF characters in the url parameter:

GET /redirect?url=https://example.com%0d%0aSet-Cookie:%20session=hijacked HTTP/1.1

The server produces:

HTTP/1.1 302 Found
Location: https://example.com
Set-Cookie: session=hijacked    ← Injected by attacker

With a double CRLF (%0d%0a%0d%0a), the attacker can inject an entirely new HTTP response body, effectively conducting reflected XSS through header injection.

Vulnerable code examples

Java / Spring — unsanitized redirect

// VULNERABLE: User-controlled URL set directly in Location header
@GetMapping("/redirect")
public void redirect(HttpServletResponse response,
                     @RequestParam String url) throws IOException {
    response.setHeader("Location", url); // CRLF in url splits the response
    response.setStatus(302);
}

PHP — header() with user input

// VULNERABLE: User input passed directly to header()
$lang = $_GET['lang']; // attacker sends "en\r\nSet-Cookie: admin=1"
header("Content-Language: " . $lang);

Secure code examples

Java — CRLF stripping

// SECURE: Strip CR/LF from any value before setting in a header
@GetMapping("/redirect")
public void redirect(HttpServletResponse response,
                     @RequestParam String url) throws IOException {
    String safeUrl = url.replaceAll("[\r\n]", ""); // Strip CRLF
    // Also validate it's a relative or trusted URL
    if (!isAllowedRedirect(safeUrl)) safeUrl = "/";
    response.sendRedirect(safeUrl); // sendRedirect also encodes the value
}

Python / Django — validate header values

from django.http import HttpResponseRedirect
import re

def redirect_view(request):
    target = request.GET.get('url', '/')
    # SECURE: Remove CRLF characters and restrict to relative URLs
    target = re.sub(r'[\r\n]', '', target)
    if not target.startswith('/') or '//' in target:
        target = '/'
    return HttpResponseRedirect(target)

C# / ASP.NET Core — use framework redirect method

// SECURE: Use framework's Redirect() method which encodes the URL
// Never set the Location header manually with user input
[HttpGet("redirect")]
public IActionResult RedirectTo(string url)
{
    if (Url.IsLocalUrl(url))
        return Redirect(url); // Framework handles encoding
    return RedirectToAction("Index", "Home");
}

What Offensive360 detects

  • User input in setHeader()/addHeader() — Direct use of tainted strings in HTTP header-setting calls
  • Unsanitized header() calls (PHP) — User input passed to PHP’s header() function without CRLF filtering
  • Cookie value injection — User-controlled data set as cookie values without CR/LF validation
  • Location header injectionResponse.Redirect() or Location: headers containing unvalidated user input

Remediation guidance

  1. Strip CRLF from all header values — Remove or encode \r and \n from any user-supplied string before including it in an HTTP header.

  2. Use framework redirect methods — Prefer Redirect(), sendRedirect(), or HttpResponseRedirect() over manually setting the Location header with user input.

  3. Validate redirect targets — Ensure redirect URLs are relative, match an allow-list, or have been signed/validated before use.

  4. Use modern framework defaults — ASP.NET Core and Spring will automatically reject headers containing CRLF characters in Response.Headers assignments.

  5. Apply output encoding — URL-encode values before including them in headers; encoded %0D%0A does not function as a CRLF at the HTTP protocol level.

References

By Offensive360 Security Research Reviewed: March 2026

Detect HTTP Response Splitting automatically

Run Offensive360 SAST on your codebase to find this and 100+ other vulnerabilities.