Today we are going to talk about Email Injections that an attacker could use it to send out spam from your mail server using your mail form.

Email injection

Email injection according to Wikipedia: Email injection is a security vulnerability that can occur in Internet applications that are used to send email messages. It is the email equivalent of HTTP Header Injection. Like SQL injection attacks, this vulnerability is one of a general class of vulnerabilities that occur when one programming language is embedded within another. When a form is added to a Web page that submits data to a Web application, a malicious user may exploit the MIME format to append additional information to the message being sent, such as a new list of recipients or a completely different message body. Because the MIME format uses a carriage return to delimit the information in a message, and only the raw message determines its eventual destination, adding carriage returns to submitted form data can allow a simple guestbook to be used to send thousands of messages at once. A malicious spammer could use this tactic to send large numbers of messages anonymously. Email injection is a type of injection attack that hits the PHP built-in mail function. It allows the malicious attacker to inject any of the mail header fields like, BCC , CC, Subject, etc., which allows the hacker to send out spam from their victims’ mail server through their victims’ contact form. For this reason, this attack is called Email Injection, or mail form spamming. This vulnerability is not limited to PHP. It can potentially affect any application that sends email messages based on input from arbitrary users. The main reason of this attack is improper user input validation or that there is no validation and filtration at all.

How does email injection work?

To explore how the email injection works, we should know exactly how the PHP email function works. Let’s have a look at PHP mail function description from PHP manual Mail() : [php] bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] ) [/php] As you can notice that it takes three mandatory parameters (“to, subject, and message”) and some other optional parameters and the function returns a Boolean value which is True or False. So let’s have a look to a vulnerable code to demonstrate this vulnerability: [php] <?php $to="webmaster@victim.com"; if (!isset($_POST["send"])){ ?> <form method="POST" action="<?=$_SERVER[‘PHP_SELF’];?>"> From: <input type="text" name="sender"> Subject : <input type="text" name="subject"> Message : <textarea name="message" rows="10" cols="60" lines="20"></textarea> <input type="submit" name="send" value="Send"> </form> <? }else{ // the form has been submitted $from=$_POST[‘sender’]; // send mail : if (mail($to,$_POST[‘subject’],$_POST[‘message’],"From: $fromn")){ echo "Your mail has been sent successfully"; }else{ ] echo "An error has been occured !"; } } ?> [/php] The previous code will be used for demonstration purposes and for explanation we will divide the previous code into 3 parts:  

The First Part

[php] <?php $to="webmaster@victim.com"; if (!isset($_POST["send"])){ ?> [/php] This code will check if the form is submitted or not. The response will be different if this code returns “True or False.” If it returns, “True,” it means that the form is not submitted. The form will show up and be waiting for user inputs. On the other hand, if it returns “False,” it means that the form is submitted, so the email will be sent.

The Second Part

[php] <form method="POST" action="<?=$_SERVER[‘PHP_SELF’];?>"> From: <input type="text" name="sender"> Subject : <input type="text" name="subject"> Message : <textarea name="message" rows="10" cols="60" lines="20"></textarea> <input type="submit" name="send" value="Send"> </form> [/php] The second part is an HTML form tag that will show up if the first part returns “True,” which asks for user inputs.

The Third Part

[php] }else{ // the form has been submitted $from=$_POST[‘sender’]; // send mail : if (mail($to,$_POST[‘subject’],$_POST[‘message’],"From: $fromn")){ echo "Your mail has been sent successfully"; }else{ ] echo "An error has been occured !"; } } ?> [/php] as you can see in the previous code specially this line mail($to,$_POST[‘subject’],$_POST[‘message’],”From: $fromn”), the Mail function takes its subject , message, and from from parameters and sends the mail. If it is successfully sent it, it will print “Your mail has been sent successfully,” and if this is an error, it will return “An error has been occurred.” Where is the problem, then? The main problem for any injection attack “Not Only Email Injection,” is trusting user inputs or improper input validation. As you can see in the third part of code, the mail function takes its argument directly from the user without any input validation, where the Mail function takes subject, message, and from from parameters without filtration and validation. So, the malicious attacker can control these values of subject , message and form parameters which the developer can use directly.

Email injection demonstration

For demonstration purposes, we will use the previous vulnerable code. Furthermore, we will submit the mail function parameters with the following values: mail(“admin@website.com” , “Call me urgent” , “Hi,nPlease call me ASAP.nBye” , “From: TrustSender@domain.comn”) The row output data looks like the following:

From the attacker point of view, there are many additional fields that can be injected in the mail header. For more information see RFC 822. For example, we can inject a CC or BCC that allows the attacker to add more recipients to the message, but before adding a new argument we have to add a new line feed that separates each field form another, the hexadecimal value for the line feed is “0x0A.” Here are some examples:

Inject Cc and Bcc after sender argument

From:sender@domain.com%0ACc:recipient@domain.co,%0ABcc:recipient1@domain.com So now, the message will be sent to the recipient and recipient1 accounts.

Inject To argument

From:sender@domain.com%0ATo:attacker@domain.com Now the message will be sent to the original recipient and the attacker account.

Inject Subject argument

From:sender@domain.com%0ASubject:This’s%20Fake%20Subject The fake subject will be added to the original subject and in some cases will replace it. It depends on the mail service behavior.

Change the body of the message

Inject a two-line feed, then write your message to change the body of the message. From:sender@domain.com%0A%0AMy%20New%20%0Fake%20Message. The fake message will be added to the original message.

Solution

Never trust user input fields. All user inputs should be considered untrusted and potentially malicious. Applications that process untrusted input may become vulnerable to attacks such as Buffer Overflows, SQL Injection, OS Commanding, Denial of Service and Email Injection. Use regular expressions to filter user data. For example, we can search for (r or n) in the input string. Use external components and libraries that provide protection against this problem like ZEND mail, PEAR mail and swift mailer. ModSecurity can put a stop to email injection on the server level. With ModSecurity, it is possible to scan the POST or GET body for BCC, CC, or To and reject any request that contains those letters.

Sources

Secure PHP wiki Webappsec projects Wikipedia Damonkohler