Bad Behavior 1.0-rc1
April 24th, 2005 by Michael Hampton
See also the blog entry announcing Bad Behavior 1.0-rc2.
Have you got anything without spam?
Gone over your bandwidth quota this month? Had to upgrade your web hosting plan? Who’s visiting your site so much? It’s those pesky spambots. They suck down your web pages repeatedly looking for links to post blog spam to, and email addresses to send conventional spam to. And then they come back the next day for more.
There has been no good way to sort out the spambots from the real users, since most of the spambots pretend to be real users. Until now.
Bad Behavior
Bad Behavior analyzes incoming requests to your server. If they match a profile of a known spambot, the spammer gets a nice error message instead of your blog.
While Bad Behavior has been tested extensively prior to this release, it is possible that there are still bugs. It’s possible that a spambot might slip through the cracks somewhere, and it’s possible that a human might be misidentified as a spambot. (They’ll get an error message explaining the situation and giving possible solutions.) If this happens please let me know so I can fix it!
Installation and Usage
Bad Behavior works as a WordPress plugin. Install it in the usual way: unzip the file and upload the bad-behavior directory to wp-content/plugins. Before running it, you may want to customize some of the variables in bad-behavior/bad-behavior-wordpress.-plugin.php
Bad Behavior can also be customized for other PHP-based software; see the bad-behavior/bad-behavior-generic.php file to get started. It will provide basic spambot blocking out of the box, but it won’t be able to keep logs (or later, some more advanced stuff) unless it’s customized to your particular PHP-based software. Just require_once("bad-behavior/bad-behavior-generic.php"); somewhere in your common PHP code to use it this way.
Thanks!
Special thanks to Mark Jaquith, Firas Durri and many others in #wordpress who assisted greatly in shaking loose and squashing many, many bugs, as well as making the code a little friendlier, before this initial release.



Denis de Bernardy Says
Just curious: How well does the plugin play with advanced cache?
Apr 25th, 2005 at 11:34 am
T. Testuser Says
This looks very promising. Just wanted to check something before trying it… you say the current version is 1.0-rc1, yet it comes up in the plugin manager as 0.9.1. The heading in bad-behavior-wordpress-plugin.php also says 0.9.1. Did you possibly forget to update the zip-file or something?
I apologize if there is an obvious Unixy programmerish answer to this that everyone understands except me.
Apr 25th, 2005 at 12:04 pm
Michael Hampton Says
Hmm. Good question, Denis. When WP-Cache serves a static page, no WordPress plugins are loaded, the database is not opened, etc. So Bad Behavior gets no chance to run. The good news is, Bad Behavior can still protect your static pages served by WP-Cache, but it will not be able to write logs to the database. To enable Bad Behavior with WP-Cache, add the following line in
wp-content/advanced-cache.php. It should be placed around line 93:require_once('plugins/bad-behavior/bad-behavior-generic.php');The new code, once complete, should read (lines 92-94):
if ($mtime + $cache_max_time > time() + $cache_time_rnd) { require_once('plugins/bad-behavior/bad-behavior-generic.php');
$meta = new CacheMeta;
This makes a fairly good example of how Bad Behavior can be integrated easily into just about any PHP-based software.
Apr 25th, 2005 at 12:06 pm
Michael Hampton Says
No, the version number is right. 1.0-rc1 shows as 0.9.1 in the plugin manager and at wp-plugins.net. The Unixy programmerish answer is that wp-plugins.net doesn’t care much for letters in the version number.
Apr 25th, 2005 at 12:07 pm
Kyle Says
This looks pretty cool. What sort of things about the request are you analyzing, and do you have a rough idea of the peformance hit a site will take with this plugin?
Apr 25th, 2005 at 4:54 pm
Denis de Bernardy Says
thanks for the howto for making it work with wp-cache.
I’ve also got a tiny feature/optimization request. I noticed while tracing your queries that the plugin does two round-trips to the server before the page loads:
- on the one side, you’ve got a DB table creation query
- on the other, you’ve got a DB cleanup query
i suspect you could register both at shutdown rather than doing them before the page loads to the user.
Else, it looks wonderfully useful. Combined a referral spam plugin (would it even be useful in your opinion?), this is likely to be good enough for me to move ahead with an automated backlink discovery plugin idea I’ve in mind.
Apr 25th, 2005 at 5:38 pm
Frank Says
Sorry, you lost me.
I can’t find “wp-content/advanced-cache.php”
there is no single-file in my wp-content / 1.5.
what can I do now to use Bad behaviour ?
Apr 25th, 2005 at 6:12 pm
Frank Says
And where can I get THAT cute plug you use here
(to submit a mail, copy the code….)
Apr 25th, 2005 at 6:14 pm
Michael Hampton Says
Kyle, the performance impact should be minimal, even with DB logging. See the FAQ.
Denis, thanks for the feedback. I’ve tried to avoid actually hooking into WP anywhere, preferring to do everything up-front. For requests which are blocked, hooking into shutdown is not feasible, but for requests which are allowed through, it could be done. I’ll consider this for a future version. As for referrer spam, Bad Behavior has proven quite useful in blocking referrer spam already, but a little extra protection never hurts!
Frank, you don’t need the hack in comment 6 unless you’re running WP-Cache, which it appears you are not. Just install Bad Behavior normally.
Apr 25th, 2005 at 6:53 pm
Denis de Bernardy Says
actually, the hack in comment 6 fails miserably because of stream errors.
the correct method is to modify the index.php file of your site. assuming you are also using referrer karma, it will thus read:
require_once(‘wp-content/plugins/bad-behavior/bad-behavior-generic.php’);
require_once (‘wp-content/referrer-karma.php’);
check_referrer();
/* Short and sweet */
define(‘WP_USE_THEMES’, true);
require(‘./wp-blog-header.php’);
Apr 25th, 2005 at 7:29 pm
Denis de Bernardy Says
I presume that enabling the plugin thereafter is redundant?
Apr 25th, 2005 at 7:30 pm
Michael Hampton Says
Denis, indeed, enabling the plugin after that is completely redundant, and you should leave it disabled if you install Bad Behavior in that manner, or you will get errors. I’ll have to look at WP-Cache again; the code I posted seems like it should work.
Podz also posted a solution based on .htaccess which might be helpful to some people.
Apr 26th, 2005 at 12:24 am
ricardo galli Says
To #6 and others regarding making it work with Wp-cache.
Are you sure you cannot do it by inserting the following tags in your plugin?
<!–mclude some.php–>
< ?php require(’some.php’); ?>
<!–/mclude–>
BTW wp-cache will [only] always execute “some.php”.
Apr 26th, 2005 at 3:26 am
Denis de Bernardy Says
I think the problem from solution at #6 came from the require being inside a class declaration. I’ve had a wide variety of bugs trying things such as this in php in the past.
I’ll likely stick to the index.php solution or try Podz’ .htaccess solution. No need to let ref karma hog resources for something that shouldn’t even make a hit in the first place.
Apr 26th, 2005 at 5:26 am