CRLF injection
What is CRLF injection?
CRLF injection is a vulnerability that lets a malicious hacker inject carriage return (CR) and linefeed (LF) characters to change the way a web application works or to confuse its administrator. There are two main malicious uses for CRLF injections: log poisoning (also called log injection, log splitting, or log forging) and HTTP response splitting.
Attackers can use CRLF injections to escalate to other types of vulnerabilities, primarily cross-site scripting (XSS). CRLF injections can also be used in web apps to influence email behavior – this is called email injection (email header injection).
Severity: | severe in rare circumstances | |
Prevalence: | discovered rarely | |
Scope: | web applications | |
Technical impact: | potential escalation to cross-site scripting | |
Worst-case consequences: | full system compromise | |
Quick fix: | use user input filtering and output encoding |
What is CRLF?
CR and LF are special characters of the ASCII table (13 and 10). They are also often referred to as \r\n after the escape codes of these two characters (\r = CR, \n = LF).
CR and LF are used (together or separately) to signify the end of a line (EoL) in operating systems and Internet protocols, including HTTP. Windows uses the CRLF combination, operating systems like Linux/UNIX and current macOS use only LF for this purpose, and legacy Mac OS used only CR.
What is log poisoning?
In a log poisoning attack based on CRLF injection, a malicious hacker injects CRLF characters into web server log files to confuse both automatic log analysis systems and system administrators browsing the logs manually.
The format of web server logs
Many web servers, such as Apache, use the NCSA Common Log Format (CLF). The format of Common Log Format entries is always the same:
host ident user date request status size
For example:
233.252.0.123 - - [11/Oct/2022:11:34:50 +0100] "GET /example.php?id=3 HTTP/1.0" 200 452
Here is how you would read this entry:
233.252.0.123
is the host – the IP address from which the request came.-
is the RFC 1413 identity of the client. The dash (-) means no data, which is the usual value.-
is the user ID of the person requesting the document. The dash (-) means no data, which is the usual value (unless there is authentication in .htaccess).[11/Oct/2022:11:34:50 +0100]
is the timestamp of when the request was received, usually in the strftime format: %d/%b/%Y:%H:%M:%S %z."GET /example.php?id=3 HTTP/1.0"
is the request line received from the client and includes the HTTP method (GET
), the requested resource and parameters (/example.php?id=3
), and the protocol (HTTP/1.0
).200
is the HTTP status code sent to the client.452
is the size of the returned object in bytes.
Another standard format is the Combined Log Format, which is similar but with a few extra fields.
Example of log poisoning
Imagine that the client is able to inject CR and LF characters into requests sent to the www.example.com web server, and it sends the following request:
https://www.example.com/example.php?id=3+HTTP%2F1.0%22+200+452%0D%0A
10.0.23.30+-+admin+%5B01%2FJan%2F2020%3A00%3A00%3A00+%2B0100%5D+%22GET+%2Fadmin.php%3Fuserid%3D12
The request contains a fake log entry, so when it is logged, the log file will include an extra line:
233.252.0.123 - - [11/Oct/2022:11:34:50 +0100] "GET /example.php?id=3 HTTP/1.0" 200 452
10.0.23.30 - admin [01/Jan/2020:00:00:00 +0100] "GET /admin.php?userid=123 HTTP/1.0" 200 452
The underlined characters represent content that was injected using CRLF injection (%0D%0A
are encoded CRLF characters).
Monitoring tools and administrators analyzing this log would be confused by this strange entry – it looks like an authenticated admin user requested the admin.php resource some time in the distant past. This confusion could allow the attacker to distract the administrator and delay log analysis in the hope of getting away with other malicious actions that would be apparent in later log entries.
What is HTTP response splitting?
In an HTTP response splitting attack, the attacker injects CRLF sequences into an HTTP response to modify the way the browser interprets HTTP headers and the request body. CRLF injections can be used to add malicious content to the request body or to add extra HTTP headers.
How the HTTP protocol uses CRLF characters
The HTTP protocol uses the CRLF character sequence in two ways:
- A single CRLF sequence means that one header ends and another begins.
- A double CRLF sequence separates all headers from the body. An HTTP request body contains data submitted by the client, while a response body usually contains website data returned by the server.
Correspondingly, there are two ways for attackers to modify HTTP traffic:
- If the attacker inserts a single CRLF into an HTTP response header, they can add a new header right after this newline. For example, they could inject a Location header to redirect the user to an attacker-controlled website. Cybercriminals can use this technique, often called HTTP header injection, for phishing or defacing.
- If the attacker inserts a double CRLF, they can prematurely terminate HTTP headers and inject malicious content before the actual website content. The injected content could include JavaScript code. The attacker can even make the browser ignore all the legitimate website content coming from the web server. This is how HTTP response splitting can lead to cross-site scripting.
Note that attackers may also inject special headers to poison proxies or web caches, allowing them to serve malicious content to many users.
Example of HTTP response splitting with XSS
In the following example, the attacker uses HTTP response splitting and HTTP header injection to send an HTTP request that adds extra headers to the HTTP response, terminates headers prematurely, and introduces a reflected cross-site scripting vulnerability.
The attacker sends the following payload in a phishing email that encourages the user to click a link or button:
http://www.example.com/example.php?id=%0d%0aContent-Length:%200%0d%0a%0d%0a
HTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2025%0d%0a%0d%0a
%3Cscript%3Ealert(1)%3C/script%3E
The payload uses CRLF injection to split the HTTP response as follows:
http://www.example.com/example.php?id=
– starting a valid request to a page with a CRLF injection vulnerability.%0d%0aContent-Length:%200
– a fake HTTP response header ofContent-Length: 0
. This causes the web browser to treat this response as terminated and start parsing the next response.
%0d%0a%0d%0aHTTP/1.1%20200%20OK
– the injected new response begins here with a double CRLF sequence followed byHTTP/1.1 200 OK
.%0d%0aContent-Type:%20text/html
– another fake HTTP response header:Content-Type: text/html
. This is required for the browser to treat this data as HTML content.%0d%0aContent-Length:%2025
– yet another fake HTTP response header:Content-Length: 25
. This instructs the browser to parse only the next 25 bytes and discard any remaining data as junk, causing it to ignore the legitimate HTTP content sent by the web server.%0d%0a%0d%0a%3Cscript%3Ealert(1)%3C/script%3E
– a double CRLF sequence signals that the headers are over and the response body starts. The injected page content is<script>alert(1)</script>
, which causes the user’s browser to display an alert instead of the actual example.php page.
Potential consequences of a CRLF injection attack
The impact of CRLF injections might seem to be limited, but they are mentioned in the OWASP top 10 2021 web application security list in the A03:2021-Injection section. Attackers can use this technique to escalate to more dangerous malicious attacks such as cross-site scripting, page hijacking, cross-user defacement, and more.
HTTP response splitting vulnerabilities allow attackers to modify HTTP headers and bypass specific security mechanisms, such as XSS filters, cookie security flags, and same-origin policy (SOP) restrictions. This opens the way to performing certain types of man-in-the-middle attacks (MITM) and exploiting cross-site request forgery (CSRF) vulnerabilities, which, in turn, could lead to sensitive information disclosure or more.
How to detect CRLF injection vulnerabilities?
The best way to detect CRLF injection vulnerabilities depends on whether they are known or unknown.
- If you only use commercial or open-source web applications and do not develop web applications of your own, it may be enough to identify the exact version of the application you are using. If the identified version is susceptible to CRLF injections, you can assume that your website or application is vulnerable. You can identify the version manually or use a suitable security tool, such as a software composition analysis (SCA) solution.
- If you develop your own web applications or want the ability to potentially find previously unknown CRLF injection vulnerabilities (zero-days) in known applications, you must be able to successfully exploit the vulnerability to be certain that it exists. This requires either performing manual penetration testing with the help of security researchers or using a security testing tool (scanner) that can use automation to exploit web vulnerabilities. Examples of such tools are Invicti and Acunetix by Invicti. We recommend using this method even for known vulnerabilities.
How to prevent CRLF injection vulnerabilities in web applications?
Many web frameworks nowadays prevent HTTP response splitting through CRLF injection by not allowing CRLF sequences to be included in HTTP headers. If your framework doesn’t perform such input validation automatically, you can use one of the following approaches:
- Change your code so you never use any user-supplied content directly in the HTTP stream. This is best practice to prevent not just CRLF injections but other injection vulnerabilities, too, and is very much recommended.
- Automatically sanitize user input and remove all newline characters before passing content into the HTTP header.
- Encode the data that you pass into HTTP headers. This will scramble the CR and LF codes if the attacker attempts to inject them.
Note that you cannot prevent log poisoning through CRLF injection at the application level simply because it is the web server’s responsibility to log requests in a safe format. Similarly, log analysis tools should parse log files, including those created by web servers, in a secure manner that does not allow for successful log poisoning or log forging attacks.
How to mitigate CRLF injection attacks?
Since CRLF injections on their own are not dangerous but can pave the way for other attacks that are, you should focus primarily on mitigating such follow-up attacks, for example, cross-site scripting attacks and web cache poisoning.
For temporary mitigation, you can rely on WAF (web application firewall) rules. With such rules, users won’t be able to provide malicious input to your web application, so no malicious code will execute in their browsers. However, since web application firewalls don’t understand the context of your application, these rules may be circumvented by attackers and should never be treated as a permanent solution.
Frequently asked questions
What are CRLF injections?
CRLF injection is a vulnerability that lets a malicious hacker inject carriage return (CR) and linefeed (LF) characters to change the way a web application works or to confuse its administrator. CRLF injections can also be used in web apps to influence email behavior – this is called email injection or email header injection.
How dangerous are CRLF injections?
CRLF injections are used by attackers for log poisoning and HTTP response splitting. Attackers can also use CRLF injections to escalate to other types of vulnerabilities, primarily cross-site scripting (XSS).
How to avoid CRLF injections?
Many web frameworks prevent HTTP response splitting through CRLF injection by not allowing CRLF sequences to be included in HTTP headers. If your framework doesn’t perform such input validation automatically, you can use general secure coding principles: input filtering and output escaping.
Classification | ID |
---|---|
CAPEC | 105 |
CWE | 93 |
WASC | 24 |
OWASP 2021 | A3 |
Related blog posts
Written by: Tomasz Andrzej Nidecki, reviewed by: Benjamin Daniel Mussler