CRLF Injection
CRLF Injection is a web application vulnerability that allows attackers to inject carriage return (CR) and line feed (LF) characters into HTTP responses or log files. By manipulating these special characters, attackers can split HTTP responses, forge log entries, inject malicious headers, or perform various other attacks that compromise application security.
What Is CRLF Injection?
CRLF Injection is a vulnerability that arises when an application includes user-controlled input in HTTP response headers or log files without properly sanitizing carriage return (\r, ASCII 13) and line feed (\n, ASCII 10) characters. In HTTP, the CRLF sequence (\r\n) serves as a delimiter that separates header fields from each other and marks the boundary between headers and the response body. When an attacker injects CRLF sequences, they can manipulate the structure of the HTTP response or log entry.
The vulnerability is particularly dangerous because it can lead to HTTP Response Splitting, where attackers inject additional headers or even entire HTTP responses. By injecting \r\n\r\n (two CRLF sequences), an attacker can terminate the headers section and begin writing content into the response body, potentially injecting malicious JavaScript or HTML. CRLF Injection can also be used to manipulate cookies, redirect users to malicious sites, or perform cross-site scripting (XSS) attacks through header injection.
Beyond HTTP responses, CRLF Injection is also a concern in logging systems. When user input containing CRLF characters is written to log files without sanitization, attackers can forge log entries, making it appear that certain events occurred when they did not. This can be used to hide malicious activity, frame other users, or bypass security monitoring systems. Despite being less publicized than SQL Injection or XSS, CRLF Injection remains a significant security risk in modern web applications.
How It Works
The application takes user input that will be used in HTTP response headers (such as redirect URLs, cookie values, or custom headers) or written to log files. Common injection points include URL parameters for redirects, form fields that set cookies, or any user-supplied data that appears in server logs.
The application directly includes the user input in an HTTP header or log entry without stripping or encoding CRLF characters. For example, a redirect might use: Location: + userInput, or a log entry might be: User logged in: + username.
The attacker provides input containing \r\n sequences, such as %0d%0aSet-Cookie:%20admin=true (URL-encoded CRLF followed by a Set-Cookie header). This specially crafted input is designed to inject new headers or log entries when processed by the application.
When the CRLF sequence is processed, it splits the response or log entry at the injection point. In HTTP responses, the injected \r\n creates a new header line, allowing the attacker to add arbitrary headers like Set-Cookie, Content-Type, or even inject a complete response body by using \r\n\r\n.
The browser or client processes the manipulated response headers, potentially setting malicious cookies, executing injected JavaScript, or redirecting to an attacker-controlled site. In logging scenarios, the forged log entries can hide attacks, create false records, or bypass security monitoring and alerting systems.
Vulnerable Code Example
@RestController
public class RedirectController {
@GetMapping("/redirect")
public ResponseEntity<Void> redirect(
@RequestParam String url,
HttpServletResponse response
) {
// VULNERABLE: User input is directly placed in
// the Location header without sanitizing CRLF
response.setHeader("Location", url);
return ResponseEntity.status(302).build();
}
}
// An attacker can inject arbitrary headers by submitting:
// /redirect?url=https://example.com%0d%0aSet-Cookie:%20admin=true
//
// URL decoded, this becomes:
// Location: https://example.com
// Set-Cookie: admin=true
//
// The CRLF (%0d%0a) splits the Location header, creating
// a new Set-Cookie header that sets admin=true.Secure Code Example
@RestController
public class RedirectController {
@GetMapping("/redirect")
public ResponseEntity<Void> redirect(
@RequestParam String url,
HttpServletResponse response
) {
// SECURE: Strip all CR and LF characters from user input
// before placing it in headers
String sanitizedUrl = url
.replaceAll("\\r", "")
.replaceAll("\\n", "");
// Additional validation: ensure URL is on allowlist
if (!isValidRedirectUrl(sanitizedUrl)) {
return ResponseEntity.badRequest().build();
}
response.setHeader("Location", sanitizedUrl);
return ResponseEntity.status(302).build();
}
private boolean isValidRedirectUrl(String url) {
// Implement allowlist of permitted redirect destinations
return url.startsWith("https://example.com/");
}
}
// With sanitization, CRLF sequences are removed before
// the URL is placed in the Location header, preventing
// header injection attacks.Types of CRLF Injection
HTTP Response Splitting
The most dangerous form of CRLF Injection. By injecting \r\n\r\n (two CRLF sequences), attackers can terminate the HTTP headers section and begin writing directly into the response body. This enables them to inject arbitrary HTML or JavaScript, set malicious cookies, override security headers like Content-Security-Policy, or even craft complete secondary HTTP responses. Response splitting can lead to cross-site scripting (XSS), cache poisoning, or session hijacking attacks.
Log Injection
When user input containing CRLF characters is written to log files, attackers can forge entirely new log entries. By injecting newlines, an attacker can make it appear that certain events occurred (such as successful authentication by other users) or hide their malicious activities by creating fake entries that confuse log analysis. This can bypass security monitoring systems, contaminate audit trails, and make incident response and forensic analysis extremely difficult.
Email Header Injection
A variant of CRLF Injection targeting email functionality. When applications construct email messages using user input without sanitizing CRLF characters, attackers can inject additional email headers such as CC, BCC, or even entire new email bodies. This can be exploited to send spam, phish users by adding hidden recipients, or inject malicious content into automated email notifications. Email header injection turns legitimate contact forms or password reset features into spam relay mechanisms.
Impact
A successful CRLF Injection attack can have serious consequences ranging from user account compromise to complete application security bypass. The impact depends on where the injection occurs and what the attacker aims to achieve.
By injecting CRLF sequences to create a Content-Type header pointing to text/html and then injecting malicious HTML/JavaScript in the response body, attackers can execute arbitrary scripts in victims' browsers, steal session cookies, capture keystrokes, or perform actions on behalf of authenticated users.
Attackers can inject Set-Cookie headers to set arbitrary cookies in victims' browsers, potentially including session identifiers that grant unauthorized access to user accounts or administrative privileges. This bypasses authentication mechanisms entirely by forging valid session cookies.
When CRLF Injection occurs in cached responses (especially on CDNs or reverse proxies), attackers can inject malicious content that gets cached and served to all subsequent users requesting the same resource. This amplifies the attack, affecting potentially thousands of users from a single injection.
Log injection enables attackers to forge log entries that hide their activities, create false records of events that never occurred, or inject entries that trigger false positives in security monitoring systems. This undermines incident detection and response capabilities, making it difficult for security teams to identify and investigate real attacks.
Prevention Checklist
The primary defense is to remove or encode \r (carriage return) and \n (line feed) characters from any user input before using it in HTTP headers or log files. Use replaceAll("\\r", "") and replaceAll("\\n", "") in Java, or URL-encode these characters if they are legitimately needed in the context.
Modern web frameworks often provide built-in protections against header injection. For example, use Spring's UriComponentsBuilder or ServletUriComponentsBuilder for constructing redirect URLs rather than manual string concatenation. These methods automatically encode special characters and prevent injection attacks.
For redirect URLs or other header values, maintain an allowlist of permitted values or patterns. Only allow redirects to trusted domains within your application. Reject any input that does not match expected formats. For example, validate that redirect URLs start with your application's domain using a strict pattern match.
Instead of manually constructing log messages with string concatenation, use structured logging libraries like SLF4J, Log4j2, or Logback with parameterized logging. These libraries automatically escape or sanitize user input, preventing log injection. For example: logger.info("User {} logged in", username) rather than logger.info("User " + username + " logged in").
HTTP/2 uses binary framing instead of text-based headers, making traditional CRLF Injection impossible. While this doesn't eliminate the risk entirely (attackers may still target HTTP/1.1 downgrade scenarios), migrating to HTTP/2 provides defense in depth. Ensure your web server and CDN support HTTP/2.
Include CRLF Injection testing in your security testing process. Automated scanners can detect common injection points, but manual code review is essential for identifying subtle vulnerabilities. Pay special attention to any code that constructs HTTP headers, redirect responses, or writes to log files using user-supplied data.
Real-World Examples
Apache HTTP Server
Multiple CRLF Injection vulnerabilities were discovered in Apache HTTP Server that allowed attackers to inject arbitrary HTTP headers through malicious requests. The vulnerabilities existed in mod_headers and other modules that processed user input without proper sanitization, enabling HTTP response splitting attacks that could lead to cache poisoning and cross-site scripting.
Ruby on Rails
Several versions of Ruby on Rails were found vulnerable to CRLF Injection in the redirect_to method. Attackers could inject CRLF sequences into redirect URLs, allowing them to inject arbitrary HTTP headers or perform HTTP response splitting. This led to widespread security updates across Rails applications and increased awareness of header injection risks.
Google Search Appliance
Security researchers discovered CRLF Injection vulnerabilities in Google Search Appliance that allowed attackers to inject HTTP headers through specially crafted search queries. The vulnerability could be exploited to perform cross-site scripting attacks by injecting JavaScript through response headers, demonstrating that even security-conscious organizations can overlook CRLF sanitization.
Node.js HTTP Parser
The Node.js HTTP parser was found to be vulnerable to CRLF Injection, allowing attackers to inject arbitrary headers through HTTP requests. The vulnerability affected many Node.js-based web applications and frameworks. The Node.js team released patches that enforced stricter header validation, rejecting requests containing CRLF sequences in header values.
Ready to Test Your Knowledge?
Put what you have learned into practice. Try identifying and fixing CRLF Injection vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.