This article explains CRLF injection (HTTP response splitting), a vulnerability where untrusted input containing carriage-return and line-feed characters is placed into HTTP response headers without filtering. The RedirectorApp lab demonstrates how an attacker can inject new headers—such as malicious Set-Cookie headers—by terminating the intended header early with encoded CRLF bytes. Understanding this vulnerability matters because it can compromise session security, poison caches, and in older systems allow response splitting to serve attacker-controlled content.
- HTTP headers are delimited by CRLFHTTP response structure is defined by carriage-return and line-feed (CRLF) characters that separate one header from the next. When an application concatenates user input directly into a header without removing CR and LF characters, those bytes are interpreted as header delimiters by the parser, allowing the attacker's text to become structural elements rather than data values.
- RedirectorApp concatenates without filteringRedirectorApp takes a URL from the query string and places it directly into the Location response header via string concatenation without stripping CR or LF. This means a newline in the input terminates the Location header early and begins a new header line controlled by the attacker, such as a Set-Cookie header of their choosing.
- Exploitation requires encoding newline charactersTo inject CRLF into a URL parameter, an attacker must encode the carriage-return and line-feed characters so they survive transport and are then interpreted as delimiters by the response parser. Once decoded by the server, these bytes break the header structure and allow injection of attacker-supplied headers like Set-Cookie values.
- Attack impacts include cookie manipulationBy injecting a Set-Cookie header, an attacker can set arbitrary session cookies or other cookie values in the response. The article notes that response splitting can also poison caches, redirect users, and in older server stacks split the response to serve attacker-controlled content.
- Modern servers reject bare CR/LF by defaultThe vulnerability is rarer today because modern web servers and frameworks reject bare CR/LF characters in header values by default, hardening the default case. However, it still appears in applications that build headers manually through string concatenation rather than using framework APIs.
- Defense requires stripping or rejecting charactersThe article prescribes four defenses: strip or reject CR and LF from any value placed in a response header; use framework APIs that validate and encode header values instead of string concatenation; validate redirect targets against an allowlist instead of reflecting raw input; and keep servers and frameworks current to benefit from built-in protections.
- Maps to OWASP Injection vulnerabilityCRLF injection (CWE-93) is classified as an Injection vulnerability under the OWASP Top 10 (2021), reflecting its status as a fundamental input-handling flaw where untrusted data changes program behavior by supplying characters with special meaning.
Bottom line: CRLF injection remains a threat wherever applications build HTTP headers through string concatenation without filtering CR and LF characters—strip or reject these characters, use framework header APIs with built-in encoding, and validate redirect targets against an allowlist to prevent attackers from injecting malicious headers like Set-Cookie.
Location response header. HTTP headers are separated by a carriage-return and line-feed (CRLF). Put those characters in your input and you are no longer supplying a value — you are writing new headers.📋 In this walkthrough
What this lab teaches
CRLF injection (HTTP response splitting, CWE-93) happens when untrusted input is placed into an HTTP response header without stripping the CR and LF characters that separate headers. An attacker who can inject a newline can add headers of their own — setting cookies, or in the worst case splitting the response into two.
The lesson: the structure of an HTTP response is defined by CRLFs. Let the user supply those and they control the structure.
How RedirectorApp builds the Location header
RedirectorApp concatenates your URL parameter into the Location header to send a redirect. It never removes CR or LF, so a newline in your input ends the Location header early and begins a new header line that you control — such as an attacker-chosen Set-Cookie.
The attack approach
- Notice your URL parameter is reflected into the Location header.
- Encode CRLF characters into the parameter so the header line can be terminated early.
- After the break, write a new header — a Set-Cookie of your choosing.
- Send it and confirm the injected header appears in the response.
Full walkthrough (spoiler)
If your extra header is not appearing, the newline encoding is being passed through literally — open the steps.
Show the step-by-step solution
- Put the redirect target in the URL parameter, then append encoded CRLF characters.
- After the CRLF, add a
Set-Cookieheader that setssession=SE_LAB_CRLF_INJECT_2026. - Submit. Because the value is concatenated without stripping CR/LF, the response now carries your injected Set-Cookie header.
- The lab detects the injected cookie header and marks you solved.
Why it works
HTTP separates headers with CRLF. The app treats your input as a flat string and copies it into a header, but the bytes you send include the very characters that mean 'next header'. The parser on the other end obeys them, so your text becomes structure — an extra header the server never intended to send.
Where this happens in the real world
Response splitting (CWE-93) can set malicious cookies, poison caches, or in older stacks split a response and serve attacker content. Modern servers and frameworks reject bare CR/LF in headers, which is why it is rarer now — but it still appears where apps build headers (redirects, custom headers) by hand. It maps to Injection (A03) in the OWASP Top 10 (2021).
How to defend against it
- Reject or strip CR and LF from any value placed in a response header.
- Use framework header APIs that validate and encode header values rather than string concatenation.
- Validate redirect targets against an allowlist instead of reflecting raw input into Location.
- Keep your server and framework current — modern versions reject malformed header characters by default.
Try it, then go further
Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.
