11 July, 2007

Slowing down the spammers

Of course there is no way to stop spammers but you can do small things to slow them down or make their life harder.

Lets take for example the sign up spam bots you may encounter for the open source forum PHPBB2. What they do is just send post variables to your sign up script to sign up new user accounts.

This fills up your forum with spammer accounts that then go on to post spam into your forum. There isn't much any web app can do against spam bots without breaking web standards but there are a few things you could do.

Say you have your example form..

‹form action="signup.php" method="post"›
‹input name="username" type="text"›
‹input name="email" type="text"›
‹/form›
and then you modify that form so that the field names are randomised for that day.
‹?php
function genField($fieldname) {
$salt = 'some random data';
return md5(date("%Y%m%d", time()).$salt.$fieldname);
}
?›
‹form action="signup.php" method="post"›
‹input name="‹?php echo genField('name'); ?›" type="text"›
‹input name="‹?php echo genField('email'); ?›" type="text"›
‹/form›
This would give your forms randomised field names that would make it more difficult for spammers to just sign up to your scripts and because the script changes on a daily basis it will never be the same.

Spam bots would now have to hit your sign up page and find out your field names before being able to sign up. It doesn't stop them but with a little work from yourself it makes the spam bot writers life more difficult.

If your form contains some form options that could be randomised it makes the spammers job even harder.
‹?php
function genField($fieldname) {
$salt = 'some random data';
return md5(date("%Y%m%d", time()).$salt.$fieldname);
}

$array = array(genField('name'), genField('email'));
shuffle($array); // randomise the array
?›
‹form action="signup.php" method="post"›
‹?php
foreach($array as $value) {
echo '‹input type="text" name="'.$value.'" /›';
}
?›
‹/form›
In this example we randomise the position our form input tags appear in so that it makes it impossible for a spam bot to crawl the page and know which of the input tags is for which field.

You can not obviously do this for every field as it would drastically mess up the user experience but some randomisation could be done if your form is large enough.

So far what we have is pretty good but a spammer could just look up the form themselves and give their spam bots the correct names for that day. Since every computer in a spam bot network has a unique IP address we can improve our function by salting by the IP address as well.

Here is the end result..
‹?php
function getRealIP() {
if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
$proxy = $_SERVER["HTTP_CLIENT_IP"];
} else {
$proxy = $_SERVER["REMOTE_ADDR"];
}
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else {
if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
$ip = $_SERVER["HTTP_CLIENT_IP"];
} else {
$ip = $_SERVER["REMOTE_ADDR"];
}
}

if (!empty($proxy)) {
$ip = $proxy;
}
return $ip;
}

function genField($fieldname) {
$salt = 'some random data';
return md5(date("%Y%m%d", time())
.getRealIP().$salt.$fieldname);
}
$array = array(genField('name'), genField('email'));
shuffle($array); // randomise the array
?›
‹form action="signup.php" method="post"›
‹?php
foreach($array as $value) {
echo '‹input type="text" name="'.$value.'" /›';
}
?›
‹/form›

0 comments: