Thursday, February 16, 2006

PHP Email Injection

Recently some of my PHP scripts have been attacked by spammer using email injection to send 100,000s of spammails...

If you are not familiar with email injection, here is the explaination.

The attack in PHP is through the mail() function.

The mail function accepts 4 arguments:
mail($sendto, $subject, $message, $header).

Some scripts accept an email address from the input form to configure the mail header so that the recipiant will see the "From" email address.

e.g.
mail("info@target.com", $_POST["subject"], $_POST["message"],
"From: ".$_POST["email"]);

?>

The accepting of input form value to build the email header opens a loophold for spammer, which enable them to add additional header information like Cc or Bcc.

For example, the spammer create his/her own version of the contact form which submit to your PHP script. In that contact form, he create <textarea name="'email'"></textarea> in replace with your original text box and fill in the following text into the <textarea>

john@123.com
Cc: abc@xyz.com,def@xyz.com,ght@xyz.com

In this case, your $_POST["email"] variable will contain the following text:
"john@123.com\nCc: abc@xyz.com,def@xyz.com,ght@xyz.com"
and your email header becomes
"From: john@123.com\nCc: abc@xyz.com,def@xyz.com,ght@xyz.com"

This eventually cause the mail function to send mail to info@target.com but also Cc to
abc@xyz.com, def@xyz.com and ght@xyz.com.

In order to solve this problem, we have to always double check the $_POST["email"] variable to make sure there aren't any vulnerable characters (' "" \n etc...) which can be use for injection attack. One of the suggestion is as below

if (preg_match(' /[\r\n,;\'"]/ ', $_POST['email'])) {
exit('Invalid email address');
}
else {
//code to send the mail
}