Preventing Email injection in a webapp form

Suppose I have a feedback form on a webpage. Something like:


<form method="get" action="testmail.php">
Email: <input name="email" type="text" value="" />
<br />
Feedback: <textarea name="feedback"></textarea>
</form>

And suppose I deal with it in PHP a bit like this:


$from = '' .POST["email"];
$feedback = '' . $_POST["feedback"];
$rtn = mail('james@rootdev.com', "Feedback from website", $feedback, "From: " . $from);

What could possibly go wrong?

Quite a lot.

OK. This is similar to the article I wrote on preventing SQL injection. You need to understand the encoding of where your data will end up (in an email rather than an SQL query this time). An attacker (specifically in this case that scourge of the internet, the spammer) can send their own emails through your form. It might sound far fetched but it really happens. And how happy will your boss/hosting service be when someone’s sent a few thousand emails through your webform one night?

Change both of the $_POST’s in the above example to $_GET and build a model. Now try a url like this (use a couple of your own emails in there (it’s easier testing this way than constructing an HTTP POST):


rubbishscript.php?email=bogusemail%0Acc:
spammedemail
&feedback=Pwnded

How does that work then? Well, since email is basically text, the email address includes a newline character (encoded as “%0A”), followed by a line which is inserted into the email.

So in the email it looks like:


to:bogusemail
cc:spammedemail

If the spammer adds a bogus email in there then they don’t alert the sysadmin with loads of failed mail delivery messages.

But why stop there?


rubbishscript.php?email=bogusemail%0Acc:spammedemail1,
spammedemail2,spammedemail3,
spammedemail4&feedback=Pwnded%20again

Get the idea?

So how do you prevent this? Well, for a start strip out any linefeeds (and carriage return just in case):


if (strpos($from, "\n") !== false) {
$from = substr($from, 0, strpos($from, "\n"));
}
if (strpos($from, "\r") !== false) {
$from = substr($from, 0, strpos($from, "\r"));
}

This will get you out of trouble in this circumstance.

There’s more on the Wikipedia article on e-mail injection and Damon Kohler’s blog.

Share this:
Share this page via Email Share this page via Stumble Upon Share this page via Digg this Share this page via Facebook Share this page via Twitter

Leave a Comment