Sending emails in PHP & email injection attacks

Posted by Muhammad Shiraz Kamboh Sunday, 27 May 2012 0 comments

PHP’s inbuilt mail() function provides very limited mail functionality. Although its easy to send text emails, but thats pretty much the only thing you can do with it. If you need extended functionality like HTML emails or attachments, you can always go through a couple of hundred pages of mail specifications at IETF .
Or you can stop trying to reinvent the wheel and use existing PHP mail libraries. Two such excellent libraries are:
  1. PHPMailer
  2. Swift Mailer
PHPMailer has been around for a long time is definitely more popular and well known but its development seems to have petered out. There has been no new releases since July 2005.
Swift Mailer on the other hand is relatively new and is more actively developed. Both websites have enough documentation and examples to get you started.
PHPMailer offers no protection against header injections. I wasn’t sure about the Swift Mailer since I don’t have much experience with it. So I put the question to Chris Corbyn, Swift Mailer’s developer. Below is his response:
Characters outside the 7-bit printable ASCII range are encoded into a 7-bit format making them incapable of affecting the header structure.
So I guess that this another reason for choosing Swift Mailer.

Email injection or mail form spamming

Spammers can hijack your seemingly innocuous looking mail form to send out spam. They do so by posting specially formatted data to your mail script. This is known as email injection or mail form spamming.
Below is the PHP code to send a simple HTML email using the mail() function.
$to = 'recipient@somedomain.xxx';
$from = 'sender@anotherdomain.xxx';
$fromname = 'Dilbert';
$subject = 'HTML Email';
$headers = "Date: ".date('r')."\n";
$headers .= "Return-Path: ".$from."\n";
$headers .= "From: ".$fromname."\n";
$headers .= "Message-ID: <".md5(uniqid(time()))."@anotherdomain.xxx>\n";
$headers .= "X-Priority: 3\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Transfer-Encoding: 8bit\n";
$headers .= 'Content-Type: text/html; charset="iso-8859-1"'."\n";
$body ='

HTML Email Body

';
mail($to, $subject, $body, $headers);
If the you run the above script (after substituting the recipient and sender email addresses) you will receive a HTML email in your inbox. Everything fine so far. Now change the value of the $from variable to the following:
$from = "sender@anotherdomain.xxx
Cc:victim@domain2.xxx";
Run the script again and you will see that two emails are sent out this time. One to the recipient@somedomain.xxx and the second to victim@domain2.xxx . This is a simplified version of mail header injection attack but the basic methodology is the same. The spammers will try to inject headers into your mail script using newlines and carriage returns.
Most often than not, variables like $from and $subject are populated by data received from a form, thus leaving the door open for possible mail injection attacks. The least you should do is to strip newlines (\n) and carriage returns (\r).

Protection against email injections and mail form spamming

As mentioned earlier, you can prevent email header injections by removing the newlines and carriage returns from the incoming data. You can use the below two functions to protect your script.
Both the functions are essentially the same. The only difference is in their usage. The first function will replace the newlines and carriage returns. The second function is a validation function which returns true if it finds newlines or carriage returns in the passed string.
function heal($str) {
 $injections = array('/(\n+)/i',
 '/(\r+)/i',
 '/(\t+)/i',
 '/(%0A+)/i',
 '/(%0D+)/i',
 '/(%08+)/i',
 '/(%09+)/i'
 );
 $str= preg_replace($injections,'',$str);
 return $str;
}
function isInjected($str) {
 $injections = array('(\n+)',
 '(\r+)',
 '(\t+)',
 '(%0A+)',
 '(%0D+)',
 '(%08+)',
 '(%09+)'
 );
 $inject = join('|', $injections);
 $inject = "/$inject/i";
 if(preg_match($inject,$str)) {
  return true;
 }
 else {
  return false;
 }
}
You can use the second function to display an error to the spammer. But it would be better to send a “403 Forbidden” or “404 Page Not Found” headers rather than to display an insulting message. The spammer just might decide to take you on your challenge.

Popular Posts

About Me

My photo
I create this Blog for learn the all kind of tutorial about web developing | HTML, Java, PHP, Graphic designing, Corel Draw, Photoshop, Micromedia Flash, Swish and many more related software and internet programming tutorials.

Followers

Blog Archive