Block Bad Queries (BBQ) is a simple script that protects your website against malicious URL requests. BBQ checks all incoming traffic and quietly blocks bad requests containing nasty stuff like eval(, base64_, and excessively long request-strings. This is a simple yet solid solution that works great for sites where .htaccess is not available. The BBQ script is available as a plugin for WordPress or standalone script for any PHP-powered website.
Installation
WP Plugin: Upload the /block-bad-queries/ directory and activate the plugin via the WP Admin. Then sit back and enjoy the automatic, behind-the-scenes protection and a more secure website. Download BBQ WP Plugin.
PHP script: The plugin and script contain identical code. To implement BBQ on a non-WP site, include the script at the beginning of each web page and you should be good to go. Download BBQ PHP script.
Verify that it’s working
Once BBQ is installed, you can verify that it’s working by requesting the following URLs from your site (example.com):
http://example.com/proc/self/environhttp://example.com/path/?q=%2e%2ehttp://example.com/path/base64_
These are just examples of the type of garbage that’s blocked by BBQ. If your server returns a 403 “Forbidden” response for these examples, BBQ is doing its thang. More tests are possible using the patterns contained in the BBQ firewall (see source code).
How it works
This is basically an adaptation of my G-series blacklists ported to PHP. It works by defining a set of regular expressions that match and block malicious URL requests. BBQ scans three parts of each request:
- The Request URI
- The Query String
- The User Agent
Checking these variables against a strategically crafted set of known attack patterns is an effective way to protect against malicious attacks.
More information
Check the following articles for more information on the underlying functionality:
- Building the Perishable Press 4G Blacklist
- Building the 5G Blacklist
- Series Summary: Building the 3G Blacklist
Plus many more articles on this and related topics in the security and .htaccess archives.
Download BBQ plugin for WordPress
Download the new and improved BBQ from the WP Plugin Directory:
WP Plugin: Block Bad Queries (BBQ)
BBQ standalone PHP script
To use BBQ on non-WP sites, include the following code for each page request:
<?php
/*
Plugin Name: Block Bad Queries (BBQ)
Plugin URI: http://perishablepress.com/block-bad-queries/
Description: Automatically protects WordPress against malicious URL requests.
Author: Jeff Starr
Author URI: http://monzilla.biz/
Version: 20121027
License: GPL v2
Usage: No configuration necessary. Upload, activate and done. BBQ blocks bad queries automically to protect your site against malicious URL requests.
Tags: security, protect, firewall, php, eval, malicious, url, request, blacklist
*/
$request_uri = $_SERVER['REQUEST_URI'];
$query_string = $_SERVER['QUERY_STRING'];
$user_agent = $_SERVER['HTTP_USER_AGENT'];
// request uri
if ( //strlen($request_uri) > 255 ||
stripos($request_uri, 'eval(') ||
stripos($request_uri, 'CONCAT') ||
stripos($request_uri, 'UNION+SELECT') ||
stripos($request_uri, '(null)') ||
stripos($request_uri, 'base64_') ||
stripos($request_uri, '/localhost') ||
stripos($request_uri, '/pingserver') ||
stripos($request_uri, '/config.') ||
stripos($request_uri, '/wwwroot') ||
stripos($request_uri, '/makefile') ||
stripos($request_uri, 'crossdomain.') ||
stripos($request_uri, 'proc/self/environ') ||
stripos($request_uri, 'etc/passwd') ||
stripos($request_uri, '/https/') ||
stripos($request_uri, '/http/') ||
stripos($request_uri, '/ftp/') ||
stripos($request_uri, '/cgi/') ||
stripos($request_uri, '.cgi') ||
stripos($request_uri, '.exe') ||
stripos($request_uri, '.sql') ||
stripos($request_uri, '.ini') ||
stripos($request_uri, '.dll') ||
stripos($request_uri, '.asp') ||
stripos($request_uri, '.jsp') ||
stripos($request_uri, '/.bash') ||
stripos($request_uri, '/.git') ||
stripos($request_uri, '/.svn') ||
stripos($request_uri, '/.tar') ||
stripos($request_uri, ' ') ||
stripos($request_uri, '<') ||
stripos($request_uri, '>') ||
stripos($request_uri, '/=') ||
stripos($request_uri, '...') ||
stripos($request_uri, '+++') ||
stripos($request_uri, '://') ||
stripos($request_uri, '/&&') ||
// query strings
stripos($query_string, '?') ||
stripos($query_string, ':') ||
stripos($query_string, '[') ||
stripos($query_string, ']') ||
stripos($query_string, '../') ||
stripos($query_string, '127.0.0.1') ||
stripos($query_string, 'loopback') ||
stripos($query_string, '%0A') ||
stripos($query_string, '%0D') ||
stripos($query_string, '%22') ||
stripos($query_string, '%27') ||
stripos($query_string, '%3C') ||
stripos($query_string, '%3E') ||
stripos($query_string, '%00') ||
stripos($query_string, '%2e%2e') ||
stripos($query_string, 'union') ||
stripos($query_string, 'input_file') ||
stripos($query_string, 'execute') ||
stripos($query_string, 'mosconfig') ||
stripos($query_string, 'environ') ||
//stripos($query_string, 'scanner') ||
stripos($query_string, 'path=.') ||
stripos($query_string, 'mod=.') ||
// user agents
stripos($user_agent, 'binlar') ||
stripos($user_agent, 'casper') ||
stripos($user_agent, 'cmswor') ||
stripos($user_agent, 'diavol') ||
stripos($user_agent, 'dotbot') ||
stripos($user_agent, 'finder') ||
stripos($user_agent, 'flicky') ||
stripos($user_agent, 'jakarta') ||
stripos($user_agent, 'libwww') ||
stripos($user_agent, 'nutch') ||
stripos($user_agent, 'planet') ||
stripos($user_agent, 'purebot') ||
stripos($user_agent, 'pycurl') ||
stripos($user_agent, 'skygrid') ||
stripos($user_agent, 'sucker') ||
stripos($user_agent, 'turnit') ||
stripos($user_agent, 'vikspi') ||
stripos($user_agent, 'zmeu')
) {
@header('HTTP/1.1 403 Forbidden');
@header('Status: 403 Forbidden');
@header('Connection: Close');
@exit;
} ?>
Note that this is the exact same script that’s contained in BBQ version 20121027, which was the last version to function as both a WordPress plugin and standalone script. Newer versions of the plugin are optimized to work better with WordPress, but this version of BBQ continues to protect non-WP sites.
Support
Questions and comments about BBQ welcome in the comments, or contact me directly.
114 Responses
Ben – October 26, 2012 •
Sounds great. Just wondering if there is likely to be any performance overhead if all incoming traffic is being checked by the script?
Jeff Starr – October 26, 2012 •
It’s a good question. BBQ is as bare-bones as possible, and should be fine unless you’re getting huge amounts of traffic. For each URI request, the script does a series of comparisons and that’s pretty much it. Not having to communicate with the database helps keep it light.
Keith Davis – October 27, 2012 •
Thanks Jeff
Alerted to this one by John Hoff and use it on all my WordPress sites.
Just updated to latest version.
Appreciate you keeping the plugin updated.
Keith Davis – October 27, 2012 •
Hi Jeff
Just updated BBQ plugin and can’t empty trash comments in WordPress dashboard.
Get the message…
“Access to the web page was denied
You are not authorised to access the web page…”
Easy to deactivate BBQ plugin, empty comments and reactivate plugin, but just letting you know.
Jeff Starr – October 27, 2012 •
It looks like WordPress is using some really long URL requests for comment/trash moderation.. I’d like to collect some examples of any URLs that are causing issues and then see what can be done. Will you post the next URL that leads to the error? (comment out any sensitive infos!) Thanks.
Keith Davis – October 27, 2012
Will do Jeff.
Grégoire Noyelle – October 27, 2012 •
Hi Jeff
Thanks a lot.
I get a bug when I try to delete all spam, the browser deny access. I was connected as admin. After desactivate the plugin, the delete button works fine.
Thanks
Jeff Starr – October 27, 2012 •
I think that may be due to the long URL requested for spam and trash deletes (anything over 255 characters is blocked). What is the URL and I can take a look..
FxB – October 27, 2012 •
Already using the 5g blacklist is there a reason to switch to bbq or not
Jeff Starr – October 27, 2012 •
Just a little bit, but the same protection will soon be available in the 6G final, so no need for BBQ if you’re rolling with 5G with plans to update.
Tom – October 27, 2012 •
Just wanted to add that the new update made it so you couldn’t delete spam comments giving you a 403 error.
Danielle Signor – October 27, 2012 •
Experiencing similar blocks as others commenting here, the first is another plugin I use, Exploit Scanner:
http://silver-rockets.com/wp-admin/tools.php?page=exploit-scanner(page is blank)Second, when trying to empty my spam comments:
http://silver-rockets.com/wp-admin/edit-comments.php?s=&comment_status=spam&pagegen_timestamp=2012-10-27+23%3A34%3A58&_total=4&_per_page=20&_page=1&_ajax_fetch_list_nonce=d6c23788da&_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&_wpnonce=88bcd416a8&_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&action=-1&comment_type=&_destroy_nonce=a9751cd9c2&_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&delete_all=Empty+Spam&paged=1&action2=-1&_destroy_nonce=a9751cd9c2&_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3DspamHope that helps you fix the issue, I definitely want to keep using BBQ, but this is a little inconvenient.
Jeff Starr – October 27, 2012 •
Plugin update! I’ve went ahead and disabled the match for long strings, and for the term
scanner. This should resolve the errors reported by Danielle, Tom, Grégoire, and Keith. Thanks to those who are providing feedback regarding BBQ. I’ll continue to update the plugin as needed and hopefully find a workaround for protection against long-character strings.Grégoire Noyelle – October 27, 2012 •
Thanks Jeff, it works now (delete spams with akismet)
Keith Davis – October 28, 2012 •
Yep, all OK now.
Appreciate that Jeff.
Danielle Signor – October 28, 2012 •
Likewise, everything works fine. Thanks for the update!
Okoth – October 28, 2012 •
Today I did a test with this plugin and the 5G. Turns out with proc/self/environ the plugin gives me a 403 and the code in the root htaccess just a page not found.
Not using them together for testing. Is this right?
Jeff Starr – October 29, 2012 •
What is the URL(s) that result in the 403 errors and I’ll take a look..
Okoth – November 3, 2012 •
I have only the 5G in the root htaccess, no BBQ, and I am trying to get a 403 with
http://example.com/hello?Permanent, but the result is 404.If have sent you my htaccess file by email, subject asdfg htaccess
I’m actually trying to block requests like this that I get a lot lately:
http://example.com/178.137.87.200/%24 and http://example.com/%5ehttp:/94.153.11.224/%24Jeff Starr – November 4, 2012
Hi Okoth, the 5G blocks the string “Permanent” only when it’s included in the request string (not the query string).
To block requests such as your examples that include an IP address, try adding this to .htaccess:
RedirectMatch 403 /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/This is actually a good idea that may end up in the 6G Blacklist.
Okoth – November 4, 2012
Thanks Jeff. Going to see if they stay out.
Yael K. Miller – October 29, 2012 •
Does this update incorporate your WordPress Add-on for 5G Blacklist?
Jeff Starr – October 29, 2012 •
Yes for the most part. It includes the widest reaching protection from the 5G, 6G, and the WP addon, but it doesn’t include everything.
Yael K. Miller – October 29, 2012
Thanks for the clarification.
Ben – October 29, 2012 •
You should check out this alternative plugin..
http://wordpress.org/extend/plugins/mute-screamer/
similar aim I guess – works really well
airos chou – October 30, 2012 •
BBQ is awesome name, i’ll try this plugin, thanks jeff