Block comment spam with bcSpamBlock
A while ago I installed Paul Butler’s JSSpamBlock on my Wordpress blog here. His original idea is simple and brilliant: Spambots don’t (yet) execute Javascript. In fact, they usually post directly to the form without even displaying the form first. By having a hidden input field that is populated by javascript, you can verify that users are hitting the page without the user even noticing. For users with JavaScript disabled (are there any of you out there), they simply have to copy/paste a small string into a textbox for verification.
Since implementing a slightly modified version of it on this blog, I have gotten zero spam posts. Now, I wanted some way to implement the same logic on some of my own custom PHP sites to prevent spam on them as well.
While working on a way to re-implement Paul’s WordPress plugin in my own sites, I came up with something pretty clever. Instead of saving a row to a database every time that the form is displayed, you can use a little cryptography to make the client pass all of the data needed to validate the request back to you on its own. The idea is sortof merger between the JSSpamBlock plugin and TCP Syncookies, which use a similar method of having the client store the data for you.
Essentially, how it works, is that the function generates a Random ID. It then encrypts the current timestamp and the random ID using PHP’s crypt() function with some cryptographic salt that is unique to each server. All three of those values (the random ID, the timestamp, and the encrypted value) are then passed to the browser. The timestamp and the encrypted value are stored in hidden <input> fields, while the random ID displayed for the user to verification. If the user has JavaScript enabled, a few lines of JavaScript copy the random ID into another textbox, and then hide that prompt, so that it is never seen by the user. If the user doesn’t have JavaScript enabled, the would have to copy/paste that random ID into the textbox themselves, similar to a captcha.
When the form is submitted, it checks to make sure that the timestamp is not too old, and then re-encrypts the passed in timestamp and random ID using the same salt value to make sure it matches the crypted value passed in from the form. If everything matches, the comment is approved, otherwise an error is displayed to the user.
I wrote this up into a simple include file that can be used for any PHP application. I also implemented a quick WordPress plugin that uses the generic version. More information about it can be found on my new bcSpamBlock home page
on October 11th, 2007 at 9:07 am
Cool. I have blogged about it.
on October 28th, 2007 at 11:05 am
Just so you know, although bcSpamBlock works effectively at blocking spam comments I realized today that it’s been blocking every trackback that’s been sent to my various posts. I found out about this when incoming links were shown in my WP 2.3.1 dashboard from both Google’s blog search and Technorati.
I tested thoroughly using my Wordpress.com blog to send trackbacks to my custom install WP blog and with bcSpamBlocker activated, the trackbacks never showed up. With it deactivated all trackbacks came through okay.
Thought you might want to know.
on November 2nd, 2007 at 4:03 am
I hope the trackback could be solved ASAP.
on November 2nd, 2007 at 11:08 pm
just modify with a add_filter to avoid trackback/pingback block:
function bc_checkfilter($content)
{
//not deal with trackback or pingback
if ( $content['comment_type'] == ‘trackback’ || $content[’comment_type’$
if (bcspamblock_verify()) return $content;
die(’Your trackback has been rejected.’);
}
// Actions
if(function_exists(’add_action’)){
add_action(’comment_form’, ‘bcspamblock_doform’);
//add_action(’comment_post’, ‘bcspamblock_checkcomment’);
}
if(function_exists(’add_filter’)){
add_filter(’preprocess_comment’,'bc_checkfilter’,2,1);
}
on November 2nd, 2007 at 11:09 pm
sorry, mis-copyinig.
function bc_checkfilter($content)
{
//not deal with trackback or pingback
if ( $content['comment_type'] == ‘trackback’ || $content['comment_type']==’pingback’) return $content;
if (bcspamblock_verify()) return $content;
die(’Your trackback has been rejected.’);
}
// Actions
if(function_exists(’add_action’)){
add_action(’comment_form’, ‘bcspamblock_doform’);
//add_action(’comment_post’, ‘bcspamblock_checkcomment’);
}
if(function_exists(’add_filter’)){
add_filter(’preprocess_comment’,'bc_checkfilter’,2,1);
}
on November 3rd, 2007 at 3:07 am
I make a version that can avoid to block pingback/trackback in my blog: http://wlx.westgis.ac.cn/455/
on November 3rd, 2007 at 6:47 pm
Thanks wlx. I have made those same changes on my own blog here and test for a day or two before committing the changes to the official wordpress plugin.
on November 11th, 2007 at 11:50 am
Sorry for the delay but I was down and out.
Thanks for the fix and the update. The plugin was sorely missed.
on December 20th, 2007 at 1:51 pm
hi,
thanks, works great.
Im using it in a custom php script.
however, the comment in line 37 should be:
if(! bcspamblock_verify()) {
not:
if(! bcspamblock_validate()) {
regards
lt
on December 20th, 2007 at 1:51 pm
hi,
thanks, works great.
Im using it in a custom php script.
however, line 37 should be:
if(! bcspamblock_verify()) {
not:
if(! bcspamblock_validate()) {
regards
lt
on March 26th, 2008 at 9:41 pm
This is a great approach in principle, and should be sufficient to block any automated bot. But, there appears to be a vulnerability in that the salt value is actually appended to the front of the bcspamblock_hidden field. On the demo page it’s $1$77dbddc7$
This means that a malicious user could theoretically generate a new bcspamblock_hidden field using the current time, and therefore avoid being timed out.
Before sending the bcspamblock_hidden field to the output page, remove the seed from the front of it
substr(bcspamblock_hidden,CRYPT_SALT_LENGTH)
and then compare only the appropriate characters in the validate function.
on July 2nd, 2008 at 1:27 am
use bcspamblock in zend form…
I want to integrate the bcspamblock and zend form, so first to do:
为了能自动防止机器人攻击,打算把bcspamblock整合到zend_form中。
1 创建element_bcSpamBlock.php文件,
<?php
class element_bcSpamBlock extends Zend_Form_Element…