Web Programming, Linux System Administation, and Entrepreneurship in Athens Georgia

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

Update 2024-10-01:

There are much better spam blocking plugins now, so this has been discontinued.

24 Comments

  1. Paul Butler

    Cool. I have blogged about it.

  2. Kirk M

    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.

  3. wlx

    I hope the trackback could be solved ASAP.

  4. wlx

    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);
    }

  5. wlx

    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);
    }

  6. wlx

    I make a version that can avoid to block pingback/trackback in my blog: https://wlx.westgis.ac.cn/455/

  7. Brandon

    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.

  8. Kirk M

    Sorry for the delay but I was down and out.

    Thanks for the fix and the update. The plugin was sorely missed. 😀

  9. lt

    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

  10. lt

    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

  11. jontiw

    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.

  12. db0

    Just to let you know that I’ve discovered a problem. In version 1.3 bcspamblock stops any trackbacks and pingbacks from reaching the site.. I’ve now tested this on three of my sites.
    All of them are hosted with Dreamhost so perhaps this is related to their setup in case you haven’t heard anyone else having the same issue.

    For now necessarily I’ve disabled the plugin

  13. Siegfried

    I’ve noticed different behaviour since wordpress 2.7 update – even if user is logged (as admin), sometimes comments are held for moderation. a bit annoying

  14. Torsten Curdt

    Any word on 2.7 support? Anyone tried?

  15. Brandon

    I’ve just upgraded this blog to 2.7 and will see what is going on.

    Thanks,
    Brandon

  16. Paul Roberts

    Testing to see if it works on 2.7

  17. Siegfried

    any conclusions? may it be browser-issue?
    I am using opera

  18. Brandon

    I did notice a problem when adding/editing comments from the admin screens in WP 2.7. I’ve changed the code to automatically approve comments if logged in to wordpress as an administrator. I have just committed a new version to the wordpress plugin repository.

  19. Alia

    Thanks, this is great!!

  20. Siegfried

    sometimes comments from regular users are held for moderation as well (users not logged, no links in comment)

  21. Brandon

    @Siegfried, I do see that behavior with my blog and never noticed that it wasn’t functioning as intended. I don’ t think that bcspamblock is causing it though. The function that checks the validation either returns the comment as-is or dies with an error message. I don’t see how that could cause it to be flagged for moderation.

  22. Jake

    This plugin works fantastically, it does need an update however, I cannot post from the admin screen as I “fail the security check” or whatever. Could you please fix this?

  23. Metal Engraver

    Im using that plugins it works perfectly!!! Cheers!!!!

  24. Chris Fisher

    I had trouble finding a plugin that would work with a theme I recently purchased that had a custom comment form and didn’t use the comment_form() function. I had all but given up. Then I found your plugin, bcSpamBlock. It appears to run flawlessly with my comment form despite not being updated in years, and has stopped SPAM completely (100%) so far. The particular theme I purchased has a thousand or more of purchases and I posted a link to your website/plugin in the support area for this theme. You might notice a big increase in downloads.

    I just want to thank you for this plugin, and to let you know about the possible increase in downloads.

    Thanks!
    Chris

1 Pingback

  1. LiangXu Wang

Leave a Reply

Your email address will not be published. Required fields are marked *

© 2025 Brandon Checketts

Theme by Anders NorenUp ↑