Fighting Forum and Message Board Spammers

I receive a lot of questions from web and forum administrators regarding spammers continuously registering on their forum and message boards. While most believe these are immature acts from a disgruntled visitor or a bored child, it usually is not. For the most part, these are what we call "link-spammers". Their mission is to find popular message boards, place a link to their website on it and retrieve email addresses for harvesting.

There are various measures you can implement to reduce the amount of linkspammers and spam-registrations to your message boards. Here, I will share them with you, along with some quick tips to help reduce the amount of spammers entering bogus names to your message boards and forums.

1. Run the board in "Enable account activation" mode = "Admin". (ACP: General Configuration)


2. Adding a hidden field, (SHOWN BELOW), will stop most bots most of the time.

    Open up your profile_add_body.tpl and add the following on line 3 (just below the <form> command):
    <input type="hidden" name="mysecretvar" value="1">
    
    Next, open up includes/usercp_register.php and find this bit around line 255:
    $passwd_sql = ''; 
       if ( $mode == 'editprofile' ) 
       { 
          if ( $user_id != $userdata['user_id'] ) 
          { 
             $error = TRUE; 
             $error_msg .= ( ( isset($error_msg) ) ? '
    ' : '' ) . $lang['Wrong_Profile']; } } else if ( $mode == 'register' ) {
    Just below that, add these lines:
    //First, weed out any remote register scripts. Easily identifyable since they have no mysecretvar set 
       if( !isset($_POST['mysecretvar']) ) 
       { 
          message_die(GENERAL_ERROR, 'Die, you spammer >:( '); 
       } 
    
    You can replace 'mysecretvar' for another variable name if you want to.


3. Hide all the "Profile Information" fields (SHOWN BELOW). This will make your board unattractive to spammers as they can't enter a web address at Registration time. Must wait to be activated, then edit their Profile.

Here is an example for the registration template. Note it is for subSilver.

    <!-- BEGIN switch_edit_profile --> 
    <tr> 
    <td class="catSides" colspan="2" height="28"> </td> 
    </tr> 
    <tr> 
    <th class="thSides" colspan="2" height="25" valign="middle">{L_PROFILE_INFO}</th> 
    </tr> 
    <tr> 
    <td class="row2" colspan="2"><span class="gensmall">{L_PROFILE_INFO_NOTICE}</span></td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_ICQ_NUMBER}:</span></td> 
    <td class="row2"> 
    <input type="text" name="icq" class="post"style="width: 100px"  size="10" maxlength="15" value="{ICQ}" /> 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_AIM}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 150px"  name="aim" size="20" maxlength="255" value="{AIM}" /> 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_MESSENGER}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 150px"  name="msn" size="20" maxlength="255" value="{MSN}" /> 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_YAHOO}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 150px"  name="yim" size="20" maxlength="255" value="{YIM}" /> 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_WEBSITE}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 200px"  name="website" size="25" maxlength="255" value="{WEBSIT$ 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_LOCATION}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 200px"  name="location" size="25" maxlength="100" value="{LOCAT$ 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_OCCUPATION}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 200px"  name="occupation" size="25" maxlength="100" value="{OCC$ 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_INTERESTS}:</span></td> 
    <td class="row2"> 
    <input type="text" class="post"style="width: 200px"  name="interests" size="35" maxlength="150" value="{INTE$ 
    </td> 
    </tr> 
    <tr> 
    <td class="row1"><span class="gen">{L_SIGNATURE}:</span><br /><span class="gensmall">{L_SIGNATURE_EXPLAIN}<br /><b$ 
    <td class="row2"> 
    <textarea name="signature"style="width: 300px"  rows="6" cols="30" class="post">{SIGNATURE}</textarea> 
    </td> 
    </tr> 
    <!-- END switch_edit_profile -->
    


4. Suppress unauthorised accounts in the Memberlist (SHOWN BELOW). This will make your board unattractive to spammers as their web address will not appear in the Memberlist until acount is authorised.
    I have enhanced my phpBB by the following 2 peaces of code. This method ensures that inactive accounts are not listed in the memberlist.

    Edit SQL query in "memberlist.php" around line 145:
    // 06-12-2004 changed by Oliver Georgi 
    // for hiding inactive users from member listing 
    // SQL query enhanced: "...WHERE user_active = 1 AND ..." 
    
    $sql  = "SELECT username, user_id, user_viewemail, user_posts, user_regdate, user_from, "; 
    $sql .= "user_website, user_email, user_icq, user_aim, user_yim, user_msnm, user_avatar, "; 
    $sql .= "user_avatar_type, user_allowavatar "; 
    $sql .=   "FROM " . USERS_TABLE . " WHERE "; 
    $sql .= "user_active = 1 AND "; 
    $sql .= "user_id <> " . ANONYMOUS . " ORDER BY $order_by";
    
    and change SQL query around line 285 like this:
    // 06-12-2004 -> enhanced by Oliver Georgi 
    // list active users only 
    // SQL query enhanced by "...user_active = 1..." 
    
    $sql  = "SELECT count(*) AS total "; 
    $sql .= "FROM " . USERS_TABLE . " WHERE "; 
    $sql .= "user_active = 1 AND "; 
    $sql .= "user_id <> " . ANONYMOUS;
    
    (Each query is just enhanced by "...user_active=1 AND..." after WHERE )


5. Suppress unauthorised accounts appearing elsewhere. (SHOWN BELOW)
    [OPEN] 
    includes/functions.php 
    
    [FIND:] 
        case 'newestuser': 
          $sql = "SELECT user_id, username 
            FROM " . USERS_TABLE . " 
            WHERE user_id <> " . ANONYMOUS . " 
            ORDER BY user_id DESC 
            LIMIT 1"; 
        break; 
    
    
    [REPLACE WITH :] 
        case 'newestuser': 
          $sql = "SELECT user_id, username 
            FROM " . USERS_TABLE . " 
            WHERE user_id <> " . ANONYMOUS . " 
            AND user_active = 1 
            ORDER BY user_id DESC 
            LIMIT 1"; 
        break; 
    
    [SAVE FILE]
    

This method ensures that all calls to get_db_stat('newestuser') will return the newest **active** user.

This will make your board unattractive to spammers as their web address will not appear as "The newest registered user" on the Forum index page or in "Administrative Statistics" until acount is authorised.


6. "Allow in Memberlist only after first post" technique (after CyberAlien) This is not necessary if you have already suppressed unauthorised accounts in the Memberlist as in tip #4.


7. Run your board in "Visual Confirmation" mode (ACP: Enable Visual Confirmation = "Yes"). This is primarily an anti-bot, anti-mass-registration technique and is therefore an alternative to 1 & 2. It is the easiest to implement in phpBB 2.0.11 upwards, as it is built in and involves minimal Admin intervention. If you look in the contrib/ folder in the download, you will see a tool called Visual Confirmation.

This adds a code to the registration page so robotic registrations are much harder. The visual confirmeration image will block all but the most elaborate bots from joining, if not all. It will not deter manual spam-registrants and therefore additional techniques need to to be considered; e.g. 1 to 5.


8. You can just switch on "Visual Confirmation" from the Configuation panel. It forces the user to type in a letter/number combination. If those signups were done by real people then it wont help, but if it was by bots (which im sure it is) it should stop them.


Here are some additional tips to help keep your board clean and running smoothly:


Update it, every time a new version comes out
Spammers are attracted to out of the box phpbb message boards. You should always keep your phpBB boards updated with the latest version. Each new release addresses current security issues found with the previous versions. Every new version you fail to install leaves you susceptible to all the vulnerabilities identified and publicised before that version was released.


Pick your mods carefully
If you don't know php, how are you going to know whether a mod is good or bad? You can't just judge it by what it appears to be doing, you have to know what it's really doing. If you're unsure about whether a mod is good or bad, go to the phpBB website and ASK. Researching your options properly and thoroughly can save you a lot of headaches.


Document Your Changes
Document all the modifications you install, so that if you have to rebuild a new version, a record of everything you added / changed is sitting there.


Know Your Vulnerabilities
Be wary of all mods. Even "safe" mods can introduce vulnerabilities. Limit the mods you install to a select few, rather than "everything you could find". This could be even more detrimental.


Make sure CAPTCHA is on
This will prevent spammers and bots from registering on your forum and polluting it with garbage posts about their crappy sites.


Remove or rename your memberlists.php
Once you've got a busy forum, nobody wants to search through a members directory, except spammers. Spammers will and do join just to be "linked" from your page.

To remove it:
    - install the user list mod in your admin
    - remove the link and image from overall_header.tpl
    - delete (or rename) the memberlist.php file



Safe input from users
If you disallow html input from users, there's very little they can do to deface your site. If you have html allowed then you're allowing them to enter 'presentation' text. Text that affects the "presentation" of your site. Make sure it's safe and is not susceptible to "sql injection".


Disallow remote avatars
Remote avatars are evil and should be banned. You have no way of knowing whether the remote avatar is an image or a script which *outputs* an image, but does some screwey stuff before it gets around to it.


Make users verify their email address before being able to sign in
If they don't give a real email address, they can't post on your board. The benefits are limited though, since it's not difficult to get a "throw away" account.


Conceal the version number
Edit overall_footer.tpl and remove the version number. If you advertise what version you are running, a spammer or script kiddy knows whether or not their exploits will work.


Limit what public information is displayed
1. Members currently online
2. Newest member
3. Search
4. All member avatars and signatures
5. All member profiles

These are not critical to browsing your forum and should be eliminated. It forces them commit a (maybe) real email address before they have full functionality. Why would Joe Schmoe want to see your members profiles anyway? Why provide him with a link to every online member so they can harvest email addresses etc. from their profiles?


Disable uploads
The easiest way to screw someone's website up is to upload a script that deletes, modifies or otherwise alters their website. It is fairly simple to make an upload script thing it's an image or a zip or any other type of file also.

If you must have uploading, do this:
    - user uploads to some directory OUTSIDE of the site
    - try and OPEN the file with something that'd normally be able to do it.

    PHP has gdi libraries, see if you can measure "i_hacked_your_site.jpg" and get its width and height. If it's not really a jpg then it's going to cause an error, so you can delete it. You can do this with php, so you don't need to "physically" fetch and open the file. It can all be automated.
    - LEAVE the files in the temporary directory till you, an adminstrator or a moderator can review it and see if it's safe.

If you upload to a folder that's publicly available, and it's really a script that screws up your site then you have a page sitting there waiting to be accessed on your site that'll screw up your site.


Use mod_rewrite
Familiarise yourself with mod_rewrite. The first reason being, "viewtopic.php?id=1234" does not fair well with search engines. Secondly, anyone looking for a phpBB board to run their script kiddie tools on can find one nice and simply by searching for "viewtopic.php". Mod_rewrite will allow you to conceal the filenames and ditch the "id=1234".

Backup Your Database
phpBB forums die when their database gets killed by some kid with a script and you're not managing your data. If you do a weekly or daily backup, then it's a minor setback if someone hacks your board. You lose a few days worth of stuff, instead of all your hard-earned members and posts.

If you do get hacked, don't reload your board right away. Find out how they did it. Dig into your web servers log files, and look at what was happening just before everything got screwed. You'll be able to tell what page they were on and their ip address. Block the ip address (also in mod_rewrite), and disable that page till you or someone who knows php can have a look at it, or you can get a newer version of phpBB.


While these tips are not guaranteed to completely rid your site of linkspamming leaches, they will go along way in deterring, if not stopping, the majority of them.