Welcome to the new design! Please report any bugs or issues, thanks :)
Web Dev + WordPress + Security

BBQ: Protect Against Malicious URL Requests

[ BBQ: Block Bad Queries ] 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.

Got BBQ? Get even more firewall protection. Upgrade to BBQ Pro »

BBQ WordPress Plugin

To use BBQ on any WordPress-powered site, install and activate the plugin via the WP Admin Area. Then sit back and enjoy the automatic, behind-the-scenes protection and a more secure website. No configuration required — BBQ is 100% plug-&-play. Now you can learn more about how BBQ works “under the hood”, or you can jump to BBQ Download.

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/environ
  • http://example.com/path/?q=%2e%2e
  • http://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.

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:

More infos 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:

BBQ standalone PHP script

To implement the BBQ script on non-WP sites, include the following code for each page request (e.g., at the beginning of each web page).

<?php
/*
Plugin Name: Block Bad Queries (BBQ)
Plugin URI: https://perishablepress.com/block-bad-queries/
Description: Automatically protects WordPress against malicious URL requests.
Author: Jeff Starr
Author URI: https://monzillamedia.com/
Version: (standalone)
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, '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;
} ?>

No changes need made to this code, so you should be good to go. Note that this script is somewhat different than the current version of the WP plugin. Newer versions of the plugin are optimized to work better with WordPress, but this version of BBQ continues to protect non-WP sites in general.

Note that any time you can update the BBQ blacklist in the standalone script using the latest patterns. Simply download the BBQ plugin and copy the regex array from the main plugin file.

Support

Feedback for BBQ welcome in the comments, or contact me directly.

Jeff Starr
About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
Banhammer: Protect your WordPress site against threats.

118 responses to “BBQ: Protect Against Malicious URL Requests”

  1. 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
      Jeff Starr 2012/10/26 5:20 pm

      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.

  2. Keith Davis 2012/10/27 3:25 am

    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.

  3. Keith Davis 2012/10/27 3:56 am

    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
      Jeff Starr 2012/10/27 3:02 pm

      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.

  4. Grégoire Noyelle 2012/10/27 6:25 am

    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
      Jeff Starr 2012/10/27 2:58 pm

      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..

  5. Already using the 5g blacklist is there a reason to switch to bbq or not

    • Jeff Starr
      Jeff Starr 2012/10/27 2:55 pm

      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.

  6. Just wanted to add that the new update made it so you couldn’t delete spam comments giving you a 403 error.

  7. Jeff Starr
    Jeff Starr 2012/10/27 4:56 pm

    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.

  8. Danielle Signor 2012/10/27 4:39 pm

    Experiencing similar blocks as others commenting here, the first is another plugin I use, Exploit Scanner (page is blank):

    http://silver-rockets.com/wp-admin/tools.php?page=exploit-scanner

    Second, when trying to empty my spam comments:

    http://silver-rockets.com/wp-admin/edit-comments.php?s=&amp;comment_status=spam&amp;pagegen_timestamp=2012-10-27+23%3A34%3A58&amp;_total=4&amp;_per_page=20&amp;_page=1&amp;_ajax_fetch_list_nonce=d6c23788da&amp;_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&amp;_wpnonce=88bcd416a8&amp;_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&amp;action=-1&amp;comment_type=&amp;_destroy_nonce=a9751cd9c2&amp;_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam&amp;delete_all=Empty+Spam&amp;paged=1&amp;action2=-1&amp;_destroy_nonce=a9751cd9c2&amp;_wp_http_referer=%2Fwp-admin%2Fedit-comments.php%3Fcomment_status%3Dspam

    Hope that helps you fix the issue, I definitely want to keep using BBQ, but this is a little inconvenient.

  9. 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

      What is the URL(s) that result in the 403 errors and I’ll take a look..

    • 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/%24

      • Jeff Starr
        Jeff Starr 2012/11/04 2:49 pm

        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.

      • Thanks Jeff. Going to see if they stay out.

  10. Does this update incorporate your WordPress Add-on for 5G Blacklist?

  11. You should check out this alternative plugin..

    http://wordpress.org/extend/plugins/mute-screamer/

    similar aim I guess – works really well

  12. airos chou 2012/10/30 1:20 am

    BBQ is awesome name, i’ll try this plugin, thanks jeff

Comments are closed for this post. Something to add? Let me know.
Welcome
Perishable Press is operated by Jeff Starr, a professional web developer and book author with two decades of experience. Here you will find posts about web development, WordPress, security, and more »
Banhammer: Protect your WordPress site against threats.
Thoughts
What's up with Plesk UI lately? Especially on Chrome it looks just awful, all kinds of broken. Come on Plesk devs get it together.
Things get stressful, I try to pray. Not always easy, but always helps to relax and regain focus.
Nice new speed checker at fastorslow.com.
Easy way to exclude certain tests from WP Site Health: Site Health Tool Manager
Excellent (and free) tool for getting tons of site SSL infos: whynopadlock.com
Everyone just stay home and hide forever. Brilliant idea.
Playing with Microsoft Edge browser on macOS. It's like 1998 all over again.