Using a Feedback Form for Spam

Have you ever received weird spam via the feedback form of your site? Something with your own address as sender or with some Mime stuff in the body? Your form is likely to be misused for spamming.

How does it work?

For PHP, for example, there is the mail function that can be used to easily send an e-mail. Most probably you'd use some code like this to send the message from your feedback form.

< ?php $msg .= "Name: " . $_POST["name"] . "\n"; $msg .= "E-Mail: " . $_POST["email"] . "\n"; $msg .= $_POST["msg"]; mail("my.e.mail@addr.es", "feedback from my site", $msg); ?>

That's simple and works well, but it's a little annoying if you want to answer that e-mail. You click the e-mail address to open a new message and have to paste the whole message into the new window for quoting. There's an easy solution: Pretend that the e-mail comes from the customer requesting some info. This can be simply done via the additional_headers parameter of mail.

< ?php $sender = "From: " . $_POST["email"] . "\r\n"; $sender = "From: " . $_POST["name"] . " <" . $_POST["email"] . ">\r\n"; // even nicer, shows the name, not the address
mail("my.e.mail@addr.es", "feedback from my site", $msg, $sender);
?>

Well. We've just introduced 2 potential spamming opportunities. Why? Let's see. For mail transport we use SMTP. Our outgoing mail might look like this (generated by mail).

From: tester < test@test.com>
To: my.e.mail@addr.es
Subject: feedback from my site

this is my message

(Before, the From would have looked something like From: webserver@mydomain.com)
So if the spammer manages to insert another field (like To, CC, or BCC), not only we would receive that e-mail but also the guy entered as CC. This works by inserting a line break into the name or e-mail address. For example, for a given name such as

Alex
CC: other@e.mail.addr.es

that would be the case.
Although this is usually not possible through a normal textbox () a post request can easily be constructed containing that linebreak and the malicious CC.

So be sure to strip out at least the characters \r and \n from name or e-mail address or just strip out any non-latin characters (people with german umlauts in their names, for example, will have to live with that).

So a quite good method would be to use this piece of code:

$name = preg_replace("|[^a-z0-9 \-.,]|i", "", $_POST["name"]);
$email = preg_replace("|[^a-z0-9@.]|i", "", $_POST["email"]);
$sender = "From: " . $name . " < " . $email . ">\r\n";
mail("my.e.mail@addr.es", "feedback from my site", $msg, $sender);

The conclusion is simple (and always the same one): Never trust any data you receive from a user.
Verify all data you receive and strip potentially harmful characters. Common bad characters are:

  • for mails: \r, \n,
  • for HTML: < , > (you could use htmlspecialchars for that),
  • for URLs: &, =,
  • complete the list in the comments ;)

Ah, the conclusion. Never trust any data you receive from a user.

, , ,

3 thoughts on “Using a Feedback Form for Spam

  1. This is a n00b mistake. PHPs best strength and worst weakness is its simplicity. Anyone off the street can be up and running in a day doing simple DB stuff and web apps. Thing is PHP doesn't stress validation nearly enough.

    The first rule of programming is to VALIDATE EVERYTHING, and I'm glad you bolded it. Anything that is coming from an untrusted source, ie users, ie remote files, etc. In nearly 99% of the cases a simple validation class or function such as an is_email() would have stopped the attempt dead in its tracks.

    In addition to this example I regularly find this in many n00b attempts at templating systems.

    http://www.url.com/script.php?page=home.php

    As you can see, this is amazingly simple to exploit. You can now basically view any file that the script can access. Password files, db connection files, etc. Not to mention the potential for some nasty cross site scripting.

    The sad thing about all of this is sever administrators spend tons of time protecting their servers from bad code when they could be doing something more productive. This ultimately results in a crippled PHP config so that the users are protected from themselves.

    In conclusion, I 110% agree with you, NEVER TRUST ANY DATA FROM ANY SOURCE ANYWHERE ANYTIME.

  2. Aparently it removed my example, unfortunatlly there is no "preview" function to this comment system, well here goes a second attempt.

    <?php
    include('header.inc.php');
    include($_GET['page']);
    include('footer.inc.php');
    ?>

  3. While validating data is important I found it far easier to simply dump comments from people contacting me into a table... then created a password protected page where I just use the mail function to send a reply. Validating is better but I didn't really see the point when I get maybe a handful of messages via my website a month.

Comments are closed.