A few days ago I started receiving spam in my spam queue, not out of the ordinary as every now and then there is a spammer who gets through my plugin and Akismet will dump it in the spam queue. But this time it was different, yes Akismet still dumped the comments in my spam queue, but it was the amount of comments I received. It easily reached 800 comments a day and besides the IP address and email address used, they were all the same. It seems some spam group found themselves a nice big botnet to play with. But wait, why didn’t my plugin AVH First Defense Against Spam stop them from showing up in my spam queue. Time to do some investigating.
I’m using a spam comment I received today although I started investigating a few days back, I just don’t have the data anymore.
Here’s one typical spam comment I received today:
IP: 220.127.116.11 Username: sem calcinha Email: email@example.com --- START OF COMMENT --- Adoro me mostrar peladinha na web cam --- END OF COMMENT ---
On a side note, it baffles me why you would post this as there’s no link to a site so what’s the point?
To start my investigation I checked my Apache access log and sure enough it was there.
18.104.22.168 - - [29/Feb/2012:05:01:52 -0800] "GET /wordpress-plugins/avh-extended-categories/ HTTP/1.1" 200 207223 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" 22.214.171.124 - - [29/Feb/2012:05:01:56 -0800] "POST /wp-comments-post.php HTTP/1.0" 302 3154 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.htm
Ok, so the spammer visits a legit page, and within 4 seconds posts a comment.
I needed more info before I could make a right decision on patching up the hole in my plugin to stop these spammers. I added some extra code to my AVH First Defense Against Spam plugin to do a bit more debugging. I added some code that would give the $_REQUEST and $_SERVER information(I replaced some info here with XXX as it’s not needed for this article).
$_SERVER -> array ( 'SERVER_SOFTWARE' => 'XXX', 'REQUEST_URI' => '/wp-comments-post.php', 'CONTENT_LENGTH' => '302', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded', 'DOCUMENT_ROOT' => '/XXX/public_html/blog', 'GATEWAY_INTERFACE' => 'CGI/1.1', 'HTTP_ACCEPT' => '*/*', 'HTTP_CACHE_CONTROL' => 'no-cache', 'HTTP_CONNECTION' => 'Keep-Alive', 'HTTP_HOST' => 'blog.avirtualhome.com', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)', 'PATH' => '/bin:/usr/bin', 'QUERY_STRING' => '', 'REDIRECT_STATUS' => '200', 'REMOTE_ADDR' => '126.96.36.199', 'REMOTE_PORT' => '61434', 'REQUEST_METHOD' => 'POST', 'SCRIPT_FILENAME' => '/XXX/public_html/blog/wp-comments-post.php', 'SCRIPT_NAME' => '/wp-comments-post.php', 'SERVER_ADDR' => 'XXX', 'SERVER_ADMIN' => 'XXX', 'SERVER_NAME' => 'blog.avirtualhome.com', 'SERVER_PORT' => '80', 'SERVER_PROTOCOL' => 'HTTP/1.0', 'SERVER_SIGNATURE' =XXX', 'UNIQUE_ID' => 'T04hxNjj2twAAFtdQs0AAAAl', 'PHP_SELF' => '/wp-comments-post.php', 'REQUEST_TIME' => '1330520516', 'argv' => array ( ), 'argc' => '0', ) $_REQUEST-> array ( 'submit' => 'Submit Comment', 'comment_post_ID' => '52', 'comment_parent' => '0', 'akismet_comment_nonce' => '5fa3aeaba9', 'subscribe' => 'subscribe', 'author' => 'sem calcinha', 'email' => 'firstname.lastname@example.org', 'url' => 'http://www.vinhobrasil.org', 'comment' => 'Adoro me mostrar peladinha na web cam', )
Ok, so from the $_REQUEST you can tell the software the spammer uses also knows to get the akistmet_comment_nonce. This is a field that Akismet introduced to stop spammers, if that field doesn’t exists or the value doesn’t match up the comment is declared spam. It’s a mechanism my AVH First Defense Against Spam plugin had implemented before Akismet, I stopped using it on my site after Akismet introduced it in their plugin. For debugging purposes I turned it on and the spammer’s software picked that field up as well, so no luck stopping a spammer that way.
Let’s have a look at the Apache log again.
"GET /wordpress-plugins/avh-extended-categories/ HTTP/1.1" 200 207223 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" "POST /wp-comments-post.php HTTP/1.0" 302 3154 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.htm
Here’s what is interesting, the spammer doesn’t click on the submit button on the article page. I can here you say “Wait, how do you know that?” and the answer is that the wp-comments-post.php is called without a referrer. On the second line you see the “-“, this is where the referrer should be, a typical comment post call should look like this:
"POST /wp-comments-post.php HTTP/1.1" 302 20 "http://blog.avirtualhome.com/2012/01/13/compile-linux-kernel-3-2-for-ubuntu-11-10/" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2"
Alright then, I know how to patch my AVH First Defense Against Spam plugin to stop this craziness. I added an extra check in my plugin and it’s been running on my site for a while now and no spam comment has come through. It even stopped some other spammers using the same technique. I still need to add some more code to the plugin before I can release it, because currently the new check isn’t optional, and an email is always send and on Tuesday, Feb 28 2012 I received nearly a thousand emails from the new check. If you want to try this version drop me a note though my contact page, select the subject AVH First Defense Against Spam and in the message request for No-Referrer version.