Welcome, please login or register

Ending the phpBB3 Spam-pocalyspe

Here at PushButton Labs, our sites powered by WordPress and phpBB are getting hit hard with spam these days. Of course, because of the awesome Akismet plug-in for WordPress, this isn’t much of an issue on that part of a site; however, phpBB is a different story. With the release of phpBB3, all of us out there running forums were breathing a sigh of relief with the thought of a period without spam. Well it now appears that the honeymoon is over. Note, this is on phpBB 3.0.4 and we’re not the only ones seeing it. It almost seems as though spambots have comprimised the phpBB registration captcha.

After hunting around the web for quite some time today, we tried to find a solution to this issue and it appeared that the only way to fix the problem was to dive into phpBB code and fix it ourselves. Disclaimer, phpBB3 doesn’t have any real plug-in system so any mods require code additions… so if you’re using phpBB you’re probably used to having to edit code to add/adjust functionality.

When it comes to stopping spammers, the best cut-off point is registration. Since users have to be registered to post on the forums, it’s logical to do the human check when registering. Usually a captcha is enough to handle this but it appears that in the case of phpBB3 it is not. So, we’ll resort to adding a simple math question that will do this check for us.

To get started, we need to edit the template for our phpBB style’s registration form so it will ask the appropriate question. In this case, our template is located at /styles/greytouch/template/ucp_register.html. To add a new field to our form, we will use the same markup that the theme is using for the other fields:

<div class="panel">
	<div class="inner"><span class="corners-top"><span></span></span>
	<h3>Are you human?</h3>
	<p>Believe it or not, a lot of users who try to register are not human.  So, we ask that you answer this simple question to prove you are and we'll let you in!</p>
	<fieldset class="fields2">
	<dl>
		<dt><label for="confirm_code">What is 2 plus 2?</label></dt>
		<dd><input type="text" name="human_question" id="human_question" size="8" class="inputbox narrow" title="human_question" /></dd>
	</dl>
	</fieldset>
	<span class="corners-bottom"><span></span></span></div>
</div>

Of course, this HTML will be placed right above the hidden fields and token in the form. I have just gone ahead and hard-coded the question into the HTML to keep things straight-forward. In this case, my question is “What is 2 plus 2.” Use any question you’d like, or even a series of questions is possible with a little tweaking.

Now that we have the form that the user is to fill out upon registering, we need to provide a little PHP logic to handle the user’s answer to make sure they are indeed human. This will require editing one of the core phpBB3 files, which I dislike doing, but I hate spammers even more. The file we want is located at /includes/ucp/ucp_register.php. Now, this file contains all of the logic that handles form validation when a user signs up to your forums. Be careful that you don’t remove anything or it could make matters worse.

First, we need to make sure that the value the user entered for our new field is accessible in our PHP code. To do so, we are going to find where the $data array is build (line 165) and add a new value to that. Here’s what the resulting array will look like (notice ‘human_question’ is now a key=>value pair.)

		$data = array(
			'username'			=> utf8_normalize_nfc(request_var('username', '', true)),
			'new_password'		=> request_var('new_password', '', true),
			'password_confirm'	=> request_var('password_confirm', '', true),
			'email'				=> strtolower(request_var('email', '')),
			'email_confirm'		=> strtolower(request_var('email_confirm', '')),
			'confirm_code'		=> request_var('confirm_code', ''),
			'lang'				=> basename(request_var('lang', $user->lang_name)),
			'tz'				=> request_var('tz', (float) $timezone),
			'human_question'	=> request_var('human_question','',true)
		);

A little bit further down (around line 180), the validate_data() function is built. We will use this function to our advantage to make sure that the value entered for ‘human_question’ is a string. Here’s what that function call will now look like (once again ‘human_question’ is added to the array).

			$error = validate_data($data, array(
				'username'			=> array(
					array('string', false, $config['min_name_chars'], $config['max_name_chars']),
					array('username', '')),
				'new_password'		=> array(
					array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
					array('password')),
				'password_confirm'	=> array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
				'email'				=> array(
					array('string', false, 6, 60),
					array('email')),
				'email_confirm'		=> array('string', false, 6, 60),
				'confirm_code'		=> array('string', !$config['enable_confirm'], 5, 8),
				'tz'				=> array('num', false, -14, 14),
				'lang'				=> array('match', false, '#^[a-z_\-]{2,}$#i'),
				'human_question'	=> array('string', false, 0, 10)
			));

Now, we just need to find an appropriate place in the process and add a check to make sure the answer matches what we expect. For this, I ended up throwing a simple “if” statement above the code for “Visual Confirmation handling” (around line 216.)

			if($data['human_question'] != '4' && strtolower($data['human_question']) != 'four'){
				$error[] = 'You did not answer the human question correctly.';
			}

And that should do it. Note, I am checking against both the numeric and written answers, as I don’t want a real user to get frustrated by me telling them their math is wrong when it really isn’t. Also, using the strtolower() function is helpful in case they are using capital letters.

By adding the error message to the $error array, when a wrong answer is provided the form will not validate and they will burn one of their login attempts. phpBB provides an option in the administrator control panel to limit the amount of registration attempts a user is given in a session. I recommend making sure this is at 5 or lower just to avoid getting hammered by some bot. To do this, navigate, in your admin panel to “Board Configuration” -> “User registration settings” and set the option “Registration attempts” to “5″ (or even lower) and save changes.

Also, another thing you can do if you don’t have a lot of user’s signing up regularly is turn on the option to have an admin confirm account registrations. To do so, navigate, in your admin panel to “Board Configuration” -> “User registration settings” and set the option “Account activation” to “By Admin” and save changes.

Notice. After making all these changes, you definitely need to purge the cache on your forum, otherwise your HTML template won’t update. You can do this under the “General” tab of the admin panel click the button that corresponds to “Purge the cache.”

Hopefully this will relieve some headaches and decrease the amount of spam you see on your site. It’s too bad we can’t have a cleaner solution but until phpBB provides a real plug-in system our options are pretty limited.

6 Comments

  • jefftunn Says:

    Ah, since we put this fix on my Make It Big In Games site, the silence is golden. There is nothing worse than having your site get found by bots, and getting spammed every 15 minutes.

  • msayre Says:

    Oh man, you read my mind. Can’t wait to implement this!

  • bArtAA Says:

    what about the option to disable registration via the forum, and only allow registration via wordpress ?

  • Flyswamper Says:

    I’m trying to implement this, but I’m not seeing the question asked on the registration page. I purged the cache and when you try to register it tells you you didn’t answer the human question correctly….

    I suspect I’m not putting the code into the ucp_register.html file in the exact-correct spot.

  • You will want to place this right above the line that reads:

    <!– IF S_COPPA –>

    Really as long as it’s within the <form></form> tags you should be ok.

  • Duber Says:

    I found out that I have to disable visual confirmation for registrations from the acp to see the question displayed on the registration page.

    Is there anyway to have both work ?

Leave a Reply

You must be logged in to post a comment.