Latest TweetsDifference between mod_alias and mod_rewrite perishablepress.com/difference…
Perishable Press

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 = Creative thinker. Passionate about free and open Web.
Archives
118 responses
  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

      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 October 27, 2012 @ 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 October 27, 2012 @ 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

      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 October 27, 2012 @ 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

      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

      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. Danielle Signor October 27, 2012 @ 4:39 pm

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

  8. Jeff Starr

    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.

  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

        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. BBQ is awesome name, i’ll try this plugin, thanks jeff

[ Comments are closed for this post ]