It is common practice for web pages and web applications to implement contact forms, which in turn send email messages to the intended recipients. Most of the time, such contact forms set headers. These headers are interpreted by the email library on the web server and turned into resulting SMTP commands, which are then processed by the SMTP server.
Unfortunately, user input is often not validated before being sent to the email library. In such cases, the contact form might be vulnerable to email header injection (also referred to as SMTP header injection or simply email injection). A malicious user may be able to introduce additional headers into the message, thereby instructing the mail server to behave differently than intended.
Email Injection is not directly dangerous to the owner of the web server, but a vulnerable contact form may be used for sending spam or for phishing. This makes it a serious application security vulnerability.
How SMTP Works
The SMTP protocol (Simple Mail Transfer Protocol) is one of the oldest protocols of the Internet. Originally, it just accepted a small set of commands that simply stated who the email sender is and who the recipient is. With time, email became much more complex, and email headers were added.
To understand how SMTP works, you need to first understand the difference between the envelope and the email body. The envelope is the initial part of the communication and it is part of the actual SMTP protocol. The following commands are part of the envelope:
MAIL FROM
: This command sets the envelope sender.RCPT TO
: This command sets the envelope recipient. It can be used multiple times if you want the message to reach many people at once.DATA
: This command begins the email payload. The payload contains email headers and the message body separated by a single empty line.
The email headers are not part of the SMTP protocol. They are interpreted by the mail client (to display the email correctly) but also by some email handling libraries in programming languages. Here are some examples of such headers:
From
: This header sets the visible sender and it can be different thanMAIL FROM
content (in most email clients, the sender provided usingMAIL FROM
is visible in theReturn-Path
header that is hidden by default).To
: This header sets the visible recipient and it can be different thanRCPT TO
content (in most email clients, the recipient provided usingRCPT TO
is visible in theDelivered-To
header that is hidden by default).
Here is an example of a simple SMTP dialogue:
> MAIL FROM:<postmaster@acunetix.com>
< 250 OK
> RCPT TO:<anna@example.com>
< 250 OK
> RCPT TO:<barbara@example.com>
< 250 OK
> DATA
< 354 Send message content; end with <CRLF>.<CRLF>
> Content-Type: text/html
> Date: Wed, 25 Dec 2019 00:00:01
> From: Santa Claus <santaclaus@acunetix.com>
> Subject: Your Gifts Are Here
> To: Not Naughty <notnaughty@example.com>
>
> Hello!
> Your gifts are here, come to the tree!
> --
> Santa
> .
< 250 OK
The above email would be received by anna@example.com and barbara@example.com. However, they would see that it was sent by Santa Claus <santaclaus@acunetix.com> (not postmaster@acunetix.com) and they would see that the recipient is Not Naughty <notnaughty@example.com>.
Most email libraries in web programming languages usually do not let you add envelope commands directly. However, they take the email headers that you supply and often convert them into equivalent SMTP commands. For example, if you add a BCC
header, the email library may take the content of that header and create additional RCPT TO
commands. With such libraries, all that the attacker needs to do is to know how to add email headers and they will be converted into equivalent SMTP commands.
Vulnerable Code
The following PHP code is an example of a typical contact form that is vulnerable to email header injection. It takes the name and email address from the input fields and prepares a list of headers for the email.
<?php
if(isset($_POST['name'])) {
$name = $_POST['name'];
$replyto = $_POST['replyTo'];
$message = $_POST['message'];
$to = 'root@localhost';
$subject = 'My Subject';
// Set SMTP headers
$headers = "From: $name \n" .
"Reply-To: $replyto";
mail($to, $subject, $message, $headers);
}
?>
A typical genuine POST request would be as follows:
POST /contact.php HTTP/1.1
Host: www.example2.com
name=Anna Smith&replyTo=anna@example.com&message=Hello
An attacker could abuse this contact form by sending the following POST request:
POST /contact.php HTTP/1.1
Host: www.example2.com
name=Best Product\nbcc: everyone@example3.com&replyTo=blame_anna@example.com&message=Buy my product!
The attacker inserts a newline (a line feed – \n
on most UNIX and Linux systems, and a carriage return and a line feed – \r\n
on Windows systems) and appends a BCC
header that containing additional email addresses. The email library converts these addresses into RCPT TO
commands and delivers the email to them in addition to the intended recipient. The attacker could use such tactics to send large numbers of messages anonymously. They may also send phishing emails where the recipient believes that these messages are originating from a trusted source.
While this vulnerability is not limited to the PHP mail
command, some email libraries are naturally resistant to it. For example, the SMTPLIB in Python is resistant because SMTP.sendmail()
needs you to specify an explicit list of recipients. If the attacker adds headers, it will only change the way that the email appears.
Detecting Email Header Injection Vulnerabilities
In order to detect email header injections automatically, the vulnerability scanner needs an intermediary service. The detection of such vulnerabilities requires out-of-band and time-delay vectors. Acunetix solves this by using the AcuMonitor as its intermediary service.
During a scan, Acunetix finds the contact form and verifies it by injecting a custom BCC
SMTP header pointing to an AcuMonitor email address. If the application causes the SMTP server to send the email to AcuMonitor, AcuMonitor knows that it is vulnerable. It then sends a notification back to Acunetix indicating that it should raise an alert for email header injection.
Mitigation
Mitigating against email header injection involves validating user input. You must not allow any newline characters in the input because they let the attacker append email headers. In general, when validating user input, the simplest and most robust way to achieve strong input validation is through a whitelist of allowed characters.
Frequently asked questions
Email header injection can happen in web contact forms that let the user send an email. If the contact form is vulnerable, an attacker can inject email headers into the email and use it for their own purposes.
Email header injection is not dangerous to the website or to the user visiting the website but the attacker can use this vulnerability to send spam or phishing emails. These emails look as if they came from the vulnerable website so they may have severe impact on your reputation.
Read a research paper that shows how common is email header injection.
Email header injection is difficult to detect and only some security scanners can do it. Acunetix is one of those scanners because it uses AcuMonitor – a technology that lets it detect out-of-band vulnerabilities.
To avoid header injection vulnerabilities as well as many other vulnerabilities, the programmer must never trust any user input. To avoid email injection, in particular, you must not allow any newline characters in contact form input because they let the attacker append email headers.
Read more about general best practices for secure programming.
Get the latest content on web security
in your inbox each week.