Thursday, August 30, 2007

Web Form Spammers

Disclaimer: As always, I don't claim to be a professional anything or actually know what I'm doing. So use the following at your own risk.

I manage one site that gets a ridiculously large amount of submitted form spam. It's a contact us page that gets hit about 30 times a day with spam. The content of course gets emailed to someone who became vocal about all the junk coming from that page. I didn't want to add an annoying human readable only verification box, so I just blocked anything containing links. This wasn't quite enough for me though, as I wanted to see where all this was coming from, and even block the same IP from even accessing the site. The following is a down and dirty method, and really isn't even very secure, but it's a good start. There is a much better method using an Apache module created by the guys at http://www.projecthoneypot.org/, but you don't always have enough control over your webserver to use a custom Apache module. The following code is all PHP and mySQL.

Check for links. If the submitted data contains "href" or "http:" return true, else return false:

function haslinks($data) {
$data = strtolower($data);
$status = strpos($data, 'href');
if ($status) {
return "1";
}
else {
$status = strpos($data, 'http:');
if ($status) {
return "1";
}
else {
return "0";
}
}
}

You can then use this to just kill the script before it does anything with the posted data:

if (haslinks($content)) {
die;
}

That will work fine for just keeping the spam out of the recipient's inbox, but let's do something a bit more devious.

if (haslinks($content)) {
include denyspam.php
die;
}

denyspam.php


$ipaddr = $REMOTE_ADDR;

include "databaseconfig.php"

$query = "INSERT INTO deniedspam (ipaddr) VALUES ('$ipaddr')";
mysql_query($query) or die('Error, insert query failed');

$myFile = "htaccess";
$fh = fopen($myFile, 'w');

$fileout = "AddType application/x-httpd-php .html\n";
$fileout .= "order allow,deny\n";

$result = mysql_query("SELECT * FROM deniedspam");

if(!$result) die("Query Failed.");

while($row = mysql_fetch_assoc($result)) {
$addr = $row['ipaddr'];
$fileout .= $addr . "\n";
}

$fileout .= "allow from all\n";


fwrite($fh, $fileout);
fclose($fh);
mysql_close();



I've created a table called deniedspam with a single varchar item to hold the offender's IP address. When a new one gets added, the file htaccess gets overwritten with all the IP addresses in the table. There is then a cron job that copies htaccess to .htaccess to keep the appropriate permissions on .htaccess.

Now I have a nice database full of known content spamming IP addresses, and can see where it's all coming from. Nine out ten spams come from an address with an open proxy, which appear to mostly be compromised machines. The rest also appear to be your average botnet zombies.

This is of course just an experiment, I don't know what the effects of a very large .htaccess file full of deny entries will have on a webserver with a high load. I'm up to about 500 entries so far and haven't seen a noticeable impact on the server load.

No comments: