What is email injection?
Email injection is a vulnerability that lets a malicious hacker abuse email-related functionality, such as email contact forms on web pages, to send malicious email content to arbitrary recipients. Because email injection is based on injecting end-of-the-line characters, it is sometimes considered a type of CRLF injection attack. Email injection is also called email header injection, SMTP header injection, or mail command injection.
|only in email-related functionality
|sending arbitrary emails to any address
|becoming an accomplice in crime, phishing
|do not pass user input to mail functions
How SMTP works
To understand SMTP header injection, we need to start by looking at SMTP – the Simple Mail Transfer Protocol.
SMTP is one of the oldest protocols of the Internet, first defined in 1981 in RFC 788. Initially, it accepted a small set of commands that declared the email sender and recipients. As email communication became more complex over time, additional headers were added.
The first crucial SMTP concept is the difference between the envelope and the email body. The envelope is the initial part of the communication and is defined by the SMTP protocol itself. The following commands make up the envelope:
- MAIL FROM: Sets the envelope sender.
- RCPT TO: Sets the envelope recipient. This command can be used multiple times if you are sending a message to multiple addresses.
- DATA: Begins the email payload, which consists of email headers and the message body, separated by a single empty line. The message is terminated by sending a line that contains a period (.) only.
The email headers are not part of the SMTP protocol. They are interpreted by mail clients (to display the email correctly) and by dedicated email libraries available in various programming languages. The two most common headers are:
- From: This header sets the visible sender, which can be a different address than set using the MAIL FROM command. In most email clients, the sender information obtained from the MAIL FROM command is placed in the Return-Path header, which is hidden by default from the user.
- To: This header sets the visible recipient, which can differ from the address set using RCPT TO. In most email clients, the recipient information from the RCPT TO command is placed in the Delivered-To header, which is hidden by default from the user.
Here is an example of a simple SMTP dialogue (
> = sent,
< = received):
> MAIL FROM:<[email protected]>
< 250 OK
> RCPT TO:<[email protected]>
< 250 OK
> RCPT TO:<[email protected]>
< 250 OK
< 354 Send message content; end with <CRLF>.<CRLF>
> Content-Type: text/html
> Date: Wed, 25 Dec 2019 00:00:01
> From: Santa Claus <[email protected]>
> Subject: Your Gifts Are Here
> To: Not Naughty <[email protected]>
> Your gifts are here, <a href="https://malicioushackersdomain.com/">come to the tree</a>!
< 250 OK
The above email from [email protected] would be received by [email protected] and [email protected]. However, to the users, it would appear that the message was sent by Santa Claus <[email protected]> (not [email protected]). Instead of their own address, they would also see that the recipient is Not Naughty <[email protected]>. Unless Anna and Barbara manually open email headers in their email client, they would not see the true sender at all.
How email injection works
Email injection works by inserting newline characters into user input. If the input is not sanitized, a malicious hacker can add email headers or modify the body of the message. By ending their malicious payload with a line that contains only a period, attackers can signal the end of the message, tricking the email server into disregarding any legitimate content that the back-end script is meant to send.
Most email libraries in web programming languages will not let you add envelope commands directly. Instead, they take the email headers you supply and often convert them into equivalent SMTP commands. For example, if you add a BCC header, your email library may take the header content and create additional RCPT TO commands. If an attacker is able to add email headers using that specific library, the headers will be converted into equivalent SMTP commands.
Example of an email injection attack
The following PHP example is a typical contact form (contact.php) vulnerable to email header injection. It takes the name and email address directly from the input fields and prepares a list of headers for the email.
$name = $_POST['name'];
$replyto = $_POST['replyTo'];
$message = $_POST['message'];
$to = 'root@localhost';
$subject = 'My Subject';
// Set SMTP headers
$headers = "From: $name \n" .
mail($to, $subject, $message, $headers);
A non-malicious POST request submitted by a user would be as follows:
POST /contact.php HTTP/1.1
name=Anna Smith&[email protected]&message=Hello
An attacker could abuse this contact form and inject email data by sending the following POST request:
POST /contact.php HTTP/1.1
name=Best Product\r\nbcc: [email protected]&[email protected]&message=Buy my product!
The attacker inserts a newline (\r\n –carriage return and line feed, CRLF) and appends a BCC header containing additional email addresses. The email library converts these addresses into RCPT TO commands and delivers the message not only to the intended recipient but also to these extra addresses. This attack also involves spoofing a replyTo header to make the recipient believe the email came from someone else ([email protected]).
Potential consequences of an email injection attack
Email injection vulnerabilities are considered a severe cybersecurity issue. While they are not directly harmful to the web application that has the security vulnerability or to its web server, email injections can allow attackers to send emails with arbitrary content to arbitrary recipients in a wide variety of attacks.
The most common email injection attack vectors include:
- Spam: A malicious user could use email injection to send spam messages. One line of code with a successful email injection could allow them to force the victim’s email server to send multiple emails with the same content to many recipients.
- Phishing: An attacker could send phishing email messages that appear to originate from the victim’s mail server, domain, and IP. As such, the attacker would be untraceable, and the blame would lie with the victim. If the victim’s application also has a cross-site scripting (XSS) vulnerability and the links in the phishing email point to this vulnerable application, the email appears even more legitimate.
- Spear phishing: Going a step further, attackers could send legitimate-looking spear-phishing email messages to selected employees at the company that runs the vulnerable application. For example, they could send the financial department a convincing email that appears to come from the CFO and urgently asks for a large bank transfer to the attacker’s account.
How to detect email injection vulnerabilities?
The best way to detect email injection vulnerabilities depends on whether they are already known or unknown.
- If you only use commercial or open-source software and do not develop software of your own, it may be enough to identify the exact version of the system or application you are using. If the identified version is susceptible to email injection, you can assume that your software is vulnerable. You can identify the version manually or use a suitable security tool, such as a software composition analysis (SCA) solution for web applications or a network scanner for networked systems and applications.
- If you develop your own software or want the ability to potentially find previously unknown email injection vulnerabilities (zero-days) in known applications, you must be able to successfully exploit the email injection vulnerability to be certain that it exists. This requires either performing manual penetration testing with the help of security researchers or using a vulnerability scanner tool that can automatically exploit web vulnerabilities. Examples of such tools are Invicti and Acunetix by Invicti. We recommend using this method even for known vulnerabilities.
Note that email injection is an out-of-band vulnerability, meaning that the attacker does not receive a direct response to their actions. To detect out-of-band vulnerabilities automatically, the vulnerability scanner needs an intermediary service. Invicti products use dedicated intermediary services to detect out-of-band vulnerabilities, including email header injections.
How to prevent email injection vulnerabilities?
To prevent email injection, developers should follow the application security best practice of treating all user input as untrusted and sanitizing it using input filtration and/or output encoding. This advice applies not just to email injection but also to most other web security vulnerabilities, including cross-site scripting, HTML injection, and SQL injection. The recommended practices for email injection are:
- Ensure that your code never directly uses content supplied by the user when specifying command parameters for functions used to send email, such as mail() in PHP.
- Automatically sanitize user input and remove all newline characters before passing content to mail functions. For input validation, use a whitelist of allowed characters and remove any that are not on the list.
- Encode all data passed to mail functions. This will scramble any CR and LF codes that attackers attempt to inject.
How to mitigate email injection attacks?
You can mitigate email injection attacks on several levels, even if email header injection vulnerabilities exist in your web applications:
- Mitigation at the development environment level: Allow your programmers to use only safe development environments, libraries, and functions. Some email libraries are naturally resistant to email injection. For example, SMTPLIB in Python is safe because SMTP.sendmail() requires you to specify an explicit list of recipients. If an attacker adds headers, it will only change the way the email appears.
- Mitigation at the web server level: Completely block unsafe email functions and create a safe email API that your developers are required to use. For example, you can disable the unsafe PHP mail() function using the disable_functions directive in php.ini. Another option is to completely block server-side email functionality and require your developers to send emails through specialized services, like AWS Amazon Simple Email Service (SES).
- Mitigation at the SMTP server level: Use a separate SMTP server for custom web applications. On that server, you can limit your email throughput and block emails that have, for example, more than 10 recipients. Set up alerts to warn the administrator about blocked attempts and any other unusual conditions. Remove these limits only for trusted applications. While this will not protect you against spear phishing through email injection, it will eliminate the risk of email injections leading to mass mailing attacks, such as spam or phishing.
Frequently asked questions
What is email injection?
Email injection is a vulnerability that lets a malicious hacker abuse email-related functionality, such as email contact forms on web pages, to send malicious email content to arbitrary recipients. Because email injection is based on injecting end-of-line characters, it is sometimes considered a type of CRLF injection attack.
How dangerous is email injection?
Email injection vulnerabilities are considered a severe cybersecurity issue. While they are not directly harmful to a vulnerable web application or its web server, email injections can allow attackers to send emails with arbitrary content to arbitrary recipients in a wide variety of attacks, including phishing, especially when combined with cross-site scripting.
How to avoid email injection?
To prevent email injection, developers should follow the application security best practice of treating all user input as untrusted and sanitizing it using input filtration and/or output encoding. This advice applies not just to email injection but also to most other web security vulnerabilities, including cross-site scripting, HTML injection, and SQL injection.