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
Sergey – October 30, 2012 •
Im also having a problem with 403 errors:
http://blog.sergeys.us/beer?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+SergeySus+(Sergey+Sus+Photography+%C2%BB+Blog)&utm_content=Google+ReaderJeff Starr – October 31, 2012 •
It’s the “:” in the query string that’s causing the issue.. Google should know better that “:” is a special-use character and must be encoded for literal use. It’s blocked by the plugin because it’s commonly seen (unencoded) in malicious attacks. Do you think I should remove the block and allow it?
Sergey – November 5, 2012
Jeff,
I do not you see the
*.*in the URL?I cant turn on the plugin as it gets 403 on all the posts from RSS feeds. What are the negatives of removing the block?
Jeff Starr – November 6, 2012
I don’t see
*.*in the URL you posted, but I do see “:” (without the quotes), which is blocked by BBQ.I’m updating the plugin soon and think I will remove “
:” from the list. Stay tuned!Honor90 – November 1, 2012 •
Hey Jeff,
Commenting to let you know that my site also got the 403, but it’s because of Chrome that I see this happened after reading the comments. It’s a tough call to keep or remove the recent update but until this issue is resolved I sadly have to disable BBQ. I work in the Chrome browser for a reason and therefore can’t have BBQ activated.
Jeff Starr – November 2, 2012 •
Thanks for the feedback, Honor90 — will get it fixed up in the next version.
Grégoire Noyelle – November 2, 2012 •
Jeff, I get an other “denied access” when I try to publish article with code inside (here is the html file. I get the problem after opy and paste this in the HTML WordPress part.
Hope it helps.
Jeff Starr – November 2, 2012 •
Hi Grégoire, Thanks for this, it will help to further improve the plugin. Will be updating soon :)
Grégoire Noyelle – November 3, 2012
Cool. Thanks so much for your great support (as always!!)
Janel Gelien – November 6, 2012 •
I can’t get Socrates 3.04 WP theme to work properly on my site if either the 5G Firewall code is included in my .htaccess file or if the BBQ plugin is installed. Any Idea which part of the code is affecting the setup of this theme? I found if I removed the word menu from the query string I could set up the menus but as far as the header and layout setup, no such luck. I would like to be able to use the plugin or firewall or both. Socrates is the only theme that seems to not work with your script but it is perfect for my new site. Any help would be appreciated.
Jeff Starr – November 8, 2012 •
Hi Janel, what are some of the URLs that aren’t loading/working and I’ll be glad to take a look. Please wrap the URLs with
<code>tags. Thanks!Janel Gelien – November 9, 2012
I’m not sure if this is what you’re asking. If for instance I go to the Socrates header setup page without the plugin activated, I can see all the options and set up the header. If I activate the plugin and bring up the same page
wp-admin/admin.php?page=functions.php?option=headerall I get is a blank page. Same with the layout option page and the settings page. As soon as I deactivate the BBQ plugin, they all appear and work properly.Jeff Starr – November 9, 2012
Yes, that’s what we’re after.. it looks like the plugin is blocking the URL because it contains an invalid character, the literal question mark, which should only appear once in the URL (unless encoded). Instead of using a question mark to append query strings, the ampersand “&” should be used.
That said, it’s a tough call whether or not to remove the block for “?” from the BBQ firewall.. it protects against a lot of malicious requests. What are your thoughts?
Janel Gelien – November 10, 2012
I am thinking that rather than change anything I might just go ahead and completely customize the site the way I want and then reactivate the plugin.
R. Richard Hobbs – November 7, 2012 •
using BBQ http://wordpress.org/extend/plugins/block-bad-queries/ in conjunction with http://wordpress.org/extend/plugins/add-from-server/ (Add From Server Plugin) seems to generate a 403. Admittedly Add From Server Plugin is outdated; I am not code-savvy enough to debug it – it is a shame because the purpose of Add From Server Plugin is to allow for adding images (that may already be in the /uploads folder…) to the WP Media Library.
What happenned is I added about one dozen images from my server ok to test if the Add From Server Plugin would work – and it did ok :) – when I went back to add the rest my site gave me ol’ “you do not have permission….” page and it generally firewalled off ALL ? the backend – none of the css would work – the site would load but without any of its styling. Also I tried to upload an image from computer to the media library and although the image uploaded, the site would not allow access to the new image via browser.
I deactivated and deleted Add From Server Plugin and BBQ, removed the db options for Add From Server Plugin and the site went back to “normal” and the uploaded image was once again accessible via browsing.
One another note is I also had your 5G rules in my htaccess (while running BBQ) – I deleted the 5G rules, cleared the caches (using W3TC for that is worth informationally….) and reinstalled BBQ. Things seem to be remaining normal for the moment. I havent reinstalled Add From Server Plugin, but it sure would be useful! I have a number of images on my server that are in the in the /uploads folder that are not in the media library – would love to get them in there somehow!
One other note is the BBQ Plugin does indeed seem to work – in spite of using the 5G rules, Bad Behavior and Akismet, I had been spending WAY too much time tweaking 404′s from bad bots and a lot of those seem to have gone away :) – I am looking forward to the next update as I am sure you must be tweaking BBQ constantly toward better functionality. Thanks
One last note is my site is running WP 3.42 in a shared hosting environment. It is CPanel based and my host allows what are probly pretty general server permissions for a shared hosting account.
Jeff Starr – November 8, 2012 •
Yes, very true :)
Also, I’m glad to look at any specific URLs/errors that aren’t loading or working with BBQ (or 5G) installed. That’s the best way to help with the next update, just be sure to wrap each of them with
<code>tags.Thanks for the feedback!
Nathan "Spanky" Briggs – November 9, 2012 •
Still having trouble with the latest and a link from twitter, because the URL includes %27.
I’ve edited BBQ on my client’s sites to remove the %27 match from. Could you include removing %27 from the match list for the next update?
Hugs,
Nathan
Jeff Starr – November 9, 2012 •
Yes, will do for the next update. Can you post an example of the twitter URL for reference?
Nathan "Spanky" Briggs – November 9, 2012
http://heidistable.com/coming-off-sugar-on-election-day-2012/?utm_source=feedburner&utm_medium=twitter&utm_campaign=Feed%3A+HeidisTable+%28Heidi%27s+Table%29(it 404s, because this client removed the post, doesn’t affect the BBQ problem, I checked)
Nathan "Spanky" Briggs – November 9, 2012
And thanks!
Jeff Starr – November 9, 2012
Perfect! Thanks Nathan.
MickeyRoush – November 12, 2012 •
You should really reconsider your blockage of %27. True it’s the root of all evil XSS attacks but those usually use more than one of those. Blocking that may also block users searching for something with it being once in the string. You should right a bypass for if there is only one occurrence of %27 and that more than one will trigger the block. I’ve created my own Block Bad Queries based from _ck_’s original plugin and I’ve been able to do so.
It also seems that you may have to whitelist the admin for certain things again. In my opinion, if an attacker already has admin privileges, there’s so much damage they can do that most plugins can’t really help against anyways.
Jeff Starr – November 12, 2012 •
Thanks for the tips, we’re working on an update to address some of these issues.
Adam – November 15, 2012 •
Hello,
I am having a problem where I started losing traffic from Facebook after installing this plugin. I had to disable it!
The URL FB was passing it as follows:
http://website.com/something.html?fb_action_ids=470231656363161&fb_action_types=og.likes&fb_source=other_multiline&action_object_map=%7B%22470231656363161%22%3A289507891167454%7D&action_type_map=%7B%22470231656363161%22%3A%22og.likes%22%7D&action_ref_map=%5B%5DCould you please fix the plugin so at least FB traffic is not blocked.
Thank you.
Jeff Starr – November 19, 2012 •
Thanks for the feedback, Adam – we’re currently updating the plugin and will try to get this fixed up for the next version. The URL example is a huge help – Thanks for posting.
R. Richard Hobbs – November 23, 2012 •
I took a minor liberty with BBQ and implemented the following in lieu of 403, beginning Line 28 ;-)
header('HTTP/1.1 418 I\'m a teapot');header('HTTP/1.1 418 I\'m a teapot');Jeff Starr – November 23, 2012 •
You are a mind-reader or something.. in the next update we’ve implemented an option for choosing your own response status and message :)
R. Richard Hobbs – November 23, 2012 •
kewl :)
My syntax seems to be off a little above; btn the curly brackets, try:
header('HTCPCP/1.1 418 I\'m a teapot');status('HTCPCP/1.1 418 I\'m a teapot');header('Connection: Close');exit;Disappointingly, my host does not seem to support 418, I keep just getting the boring ol’ 403.
J32 Design – November 24, 2012 •
Hi Jeff,
I am using a plugin called WP No External Links which masks my outgoing links. It changes the link from lets say http://www.google.com to j32design.com/goto/http://www.google.com and uses 302 redirect.
I use this plugin and the BBQ plugin since quite a long time now, but as far as I could see in google webmaster tools I started to get 403 Permission Denied errors for all my outgoing links somewhere in the end of October.. The redirects work fine as soon as I turn the BBQ plugin off. Now, I really don’t want to turn it off.
Is there anything you or I can do to make them both work together?
Thank you in advance for your time.
Jeff Starr – November 26, 2012 •
The reason the URLs are blocked in this case is because they include
http://unencoded in the request string. Unfortunately that particular string is common among malicious requests, so is blocked in the BBQ plugin. The question now is do we remove protection for requests containing unencodedhttp://? What are your thoughts?J32 Design – November 29, 2012 •
Thank you Jeff for getting back to me. For now I decided to turn of the plugin that masks my outgoing links until I find a better solution. The masking plugin has an option where it replaces the url with a random number, which seems to work, but I have to see how it will effect my blog regarding speed.