Zend PHP 7 Certification – Security – Email Injection

This post covers the Email Injection section of the PHP Security chapter when studying for the Zend PHP 7 Certification.

PHP contains functions and classes that assist with sending mail, and as a result, some security measures should be taken to prevent injection of spam-related content into the email.

When sending an email using the standard mail() function, you may have code that looks similar to the below.

mail("customer@example.com", "Contact Form Reply", $message, "From: $email" );

The code above sends the message to customer@example.com in response to their contact form submission to the email address stored in the $email variable, which is typically obtained from the web form.

If the script takes no effort to validate the $email variable before calling mail(), it is possible for a spammer to inject additional lines into the $email variable like so:

some-email-address@example.com
CC: another-email-address@example.com, yet-another-email-addresses@example.com, etc-etc@example.com

The PHP mail() function will insert those lines and deliver the mail to everyone on that list. This is a simple example of email injection.

So to filter valid emails for use in the recipient email field, you can use the filter_var() function.

<?php
$email = filter_var($_POST['recipient_email'], FILTER_VALIDATE_EMAIL);

if ($email === FALSE) {
    echo 'Invalid email';
    exit(1);
}

The filter_var() function filters a variable with a specified filter. The two parameters used in this function include the variable to check against, and the in-built filter to be used.

Some of the filters that can be used include:

  • FILTER_VALIDATE_EMAIL
  • FILTER_VALIDATE_FLOAT
  • FILTER_VALIDATE_INT
  • FILTER_VALIDATE_IP

This will make sure your users only supply singular, valid emails, which you can then pass to the mail() function.

When the mail() function talks directly to an SMTP server, starting lines with full stops will need to be prevented in the message body. Therefore a simple str_replace() function should be used.

$body = str_replace("\n.", "\n..", $body);

It is also possible to inject via the subject, as well, but since there is no FILTER_VALIDATE_EMAIL_SUBJECT filter available when using filter_var(), the filtering will need to be performed yourself.

$subject = str_ireplace(array("\r", "\n", '%0A', '%0D'), '', $_POST['subject']);

Other techniques of preventing email injection include:

  • Do not provide open relays
  • Open the SMTP port only if essential
  • Use a ‘tarpits’ technique to slow requests as a means of dissuading attacks. This delays incoming connections with delayed response

View the other sections:

Note: This article is based on PHP version 7.0.