HTTP Splitting

ID

python.http_splitting

Severity

critical

Resource

Injection

Language

Python

Tags

CWE:113, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1

Description

Improper Neutralization of CR/LF Sequences in HTTP Headers ('HTTP Request/Response Splitting').

HTTP response splitting occurs when user input is unsafely incorporated into HTTP response headers. Attackers exploit these vulnerabilities by injecting CR/LF (Carriage Return plus Line Feed) characters, effectively splitting the HTTP response into two separate responses.

This vulnerability is often referred to as HTTP Header Manipulation.

Rationale

HTTP Response Splitting (CWE-113) arises when user input is included in an HTTP response header without proper validation. If an attacker is able to inject CR (\r) and LF (\n) characters, they can prematurely terminate the header section and inject arbitrary headers or even body content. This can lead to a wide range of attacks, including header injection, web cache poisoning, and cross-site scripting (XSS).

In Python, especially with frameworks like Flask, a common mistake is directly assigning untrusted input to a response header without validating for control characters. Here’s an example of a vulnerable pattern:

Vulnerable Example using Flask
from flask import Flask, request, Response

app = Flask(__name__)

@app.route("/header")
def custom_header():
    header_value = request.args.get("val", "")
    response = Response("Check headers")
    response.headers["X-Test"] = header_value  # FLAW
    return response

In this case, a user can pass a value like:

/header?val=legit%0D%0ASet-Cookie:%20hacked=true

This will cause the server to include a malicious Set-Cookie header in the response, which can be used to hijack sessions or alter cache behavior.

HTTP response splitting can lead to serious security concerns such as:

  • Cross-Site Scripting (XSS): Leveraging the split response to inject script content into another user’s browser.

  • Web Cache Poisoning: Exploiting vulnerable proxy servers or caching mechanisms to cache a poisoned response.

  • Session Fixation: Forcing a user into a session where the session ID is specified by the attacker.

Mitigating this requires diligent input validation and proper handling of HTTP headers to ensure that malicious headers cannot be injected.

Remediation

To remediate this issue in Flask applications:

  1. Sanitize all header values: Remove or reject carriage return (\r) and line feed (\n) characters from inputs used in headers.

  2. Perform strict input validation: Accept only values matching a safe pattern or whitelist.

  3. Use safe helper methods: When possible, rely on libraries or frameworks that encode or validate header values internally.

Secure Example
from flask import Flask, request, Response, abort
import re

app = Flask(__name__)

@app.route("/header")
def safe_custom_header():
    header_value = request.args.get("val", "")

    # Reject CR or LF to prevent header injection
    if "\r" in header_value or "\n" in header_value:
        abort(400, "Invalid header value")

    # Alternatively: strip CR/LF characters
    sanitized_value = re.sub(r'[\r\n]', '', header_value)

    response = Response("Check headers")
    response.headers["X-Test"] = sanitized_value
    return response

By stripping or rejecting CRLF characters, we ensure that the header is treated as a single logical line and cannot be split or injected. This aligns with secure development practices and common compliance frameworks (e.g., OWASP Top 10 A03:2021 – Injection).

Configuration

The detector has the following configurable parameters:

  • sources, that indicates the source kinds to check.

  • neutralizations, that indicates the neutralization kinds to check.

Unless you need to change the default behavior, you typically do not need to configure this detector.

References