Spring Sale! Save 30% on all books w/ code: PLANET24
Web Dev + WordPress + Security

5G Blacklist 2013

[ 5G (2013) ] Following up on much feedback (and this post), here is an update for the 5G Blacklist for 2013. As explained in the 2012 article (and elsewhere), the 5G Blacklist helps reduce the number of malicious URL requests that hit your website. It’s one of many ways to improve the security of your site and protect against evil exploits, bad requests, and other nefarious garbage. If your site runs on Apache and you’re familiar with .htaccess, the 5G is an effective way to secure your site against malicious HTTP requests and other suspect activity.

Update: Check out the new and improved 6G Firewall »

About the 5G Blacklist

The 5G Blacklist is a simple, flexible blacklist that checks all URI requests against a series of carefully constructed HTAccess directives. This happens quietly behind the scenes at the server level, saving resources for stuff like PHP and MySQL for all blocked requests.

How it works

Blacklists can block just about any part of a request: IP, user agent, request string, query string, referrer, and everything in between. But IP addresses change constantly, and user agents and referrers are easily spoofed. As discussed, request strings yield the best results: greater protection with fewer false positives.

The 5G works beautifully with WordPress, and should help any site conserve bandwidth and server resources while protecting against malicious activity.

5G Blacklist 2013

Here is the third version of the 5th generation blacklist:

# 5G BLACKLIST/FIREWALL (2013)
# @ https://perishablepress.com/5g-blacklist-2013/

# 5G:[QUERY STRINGS]
<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteBase /
	RewriteCond %{QUERY_STRING} (\"|%22).*(<|>|%3) [NC,OR]
	RewriteCond %{QUERY_STRING} (javascript:).*(\;) [NC,OR]
	RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3) [NC,OR]
	RewriteCond %{QUERY_STRING} (\\|\.\./|`|=\'$|=%27$) [NC,OR]
	RewriteCond %{QUERY_STRING} (\;|\'|\"|%22).*(union|select|insert|drop|update|md5|benchmark|or|and|if) [NC,OR]
	RewriteCond %{QUERY_STRING} (base64_encode|localhost|mosconfig) [NC,OR]
	RewriteCond %{QUERY_STRING} (boot\.ini|echo.*kae|etc/passwd) [NC,OR]
	RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC]
	RewriteRule .* - [F]
</IfModule>

# 5G:[USER AGENTS]
<IfModule mod_setenvif.c>
	# SetEnvIfNoCase User-Agent ^$ keep_out
	SetEnvIfNoCase User-Agent (binlar|casper|cmsworldmap|comodo|diavol|dotbot|feedfinder|flicky|ia_archiver|kmccrew|nutch|planetwork|purebot|pycurl|skygrid|sucker|turnit|vikspider|zmeu) keep_out
	<limit GET POST PUT>
		Order Allow,Deny
		Allow from all
		Deny from env=keep_out
	</limit>
</IfModule>

# 5G:[REQUEST STRINGS]
<IfModule mod_alias.c>
	RedirectMatch 403 (https?|ftp|php)\://
	RedirectMatch 403 /(https?|ima|ucp)/
	RedirectMatch 403 /(Permanent|Better)$
	RedirectMatch 403 (\=\\\'|\=\\%27|/\\\'/?|\)\.css\()$
	RedirectMatch 403 (\,|\)\+|/\,/|\{0\}|\(/\(|\.\.\.|\+\+\+|\||\\\"\\\")
	RedirectMatch 403 \.(cgi|asp|aspx|cfg|dll|exe|jsp|mdb|sql|ini|rar)$
	RedirectMatch 403 /(contac|fpw|install|pingserver|register)\.php$
	RedirectMatch 403 (base64|crossdomain|localhost|wwwroot|e107\_)
	RedirectMatch 403 (eval\(|\_vti\_|\(null\)|echo.*kae|config\.xml)
	RedirectMatch 403 \.well\-known/host\-meta
	RedirectMatch 403 /function\.array\-rand
	RedirectMatch 403 \)\;\$\(this\)\.html\(
	RedirectMatch 403 proc/self/environ
	RedirectMatch 403 msnbot\.htm\)\.\_
	RedirectMatch 403 /ref\.outcontrol
	RedirectMatch 403 com\_cropimage
	RedirectMatch 403 indonesia\.htm
	RedirectMatch 403 \{\$itemURL\}
	RedirectMatch 403 function\(\)
	RedirectMatch 403 labels\.rdf
	RedirectMatch 403 /playing.php
	RedirectMatch 403 muieblackcat
</IfModule>

# 5G:[REQUEST METHOD]
<ifModule mod_rewrite.c>
	RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
	RewriteRule .* - [F]
</IfModule>

# 5G:[BAD IPS]
<limit GET POST PUT>
	Order Allow,Deny
	Allow from all
	# uncomment/edit/repeat next line to block IPs
	# Deny from 123.456.789
</limit>

To use: include the entire 5G Blacklist in the root .htaccess file of your site. Remember to backup your original .htaccess file before making any changes. Test thoroughly while enjoying your favorite beverage. If you encounter any issues, please read the troubleshooting tips and/or leave a comment to report a bug.

Note: in some cases it may be necessary to place the QUERY STRING rules before WP-permalink rules.

Update (2015/04/03): removed jakarta from the user-agent portion of the list. Reason? LinkedIn actually includes the term “jakarta” in their user-agent string:

LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)

</update>

Pre-changelog notes

The changes made for 5G 2013 are aimed at maximizing compatibility. Unfortunately, a number of required changes are due to improper coding and ignoring HTTP specifications. As mentioned previously, using unsafe characters in URLs obsoletes security measures that are based on pattern-matching, which is integral to the process of blocking malicious activity.

To illustrate, it is possible to protect against a wide range of malicious requests by blocking unsafe characters such as unencoded question marks “?” included within the query string. Firewalls, blacklists, security plugins and scripts are able to safely block such bad requests UNTIL some widely used service such as Google Adwords decides to start including multiple unencoded question marks in their query strings. Suddenly blocking potentially dangerous “?” requests is useless because nobody wants to block legitimate (Google) traffic.

Moral of the story: if you develop for the Web, contribute to its security by encoding your URLs according to spec. If you use security plugins, firewalls/blackists, and scripts that rely on pattern-matching to protect your site, please encourage and educate others about the importance of adhering to HTTP specifications.</rant>

Changelog

Removed from QUERY STRINGS

  • Square brackets “[” and “]” (details)
  • Colon “:” (details)
  • Unencoded question mark “\?” (WP previews, Piwik, Adwords, et al)
  • Removed “(menu|mod|path|tag)\=\.?/?” (WP menus, WP Super Cache, Joomla, Googlebot, et al)
  • Removed “environ” (common string)
  • Removed “scanner” (various WP plugins)
  • Removed “%3E” (common string)
  • Escaped backslash, from “\” to “\\

Removed from USER AGENTS

  • Commented out match for blank/empty user-agent “^$” (PayPal, WP-Piwik, et al)
  • Removed match for “libwww” (used by Lynx browser)

Removed from REQUEST STRINGS

  • Double forward slash “//” (Pingdom, gtmetrix, et al)
  • Removed match for “/cgi/” (Fancy indexes, Authentication)

Added to QUERY STRINGS (5G 2013)

  • TRACE” and “TRACK
  • base64_encode.*\(
  • \|%3E
  • GLOBALS(=|\[|\%)
  • REQUEST(=|\[|\%)
  • `
  • (\"|%22).*(<|>|%3)
  • (<|%3C).*script.*(>|%3)
  • (javascript:).*(\;)
  • (\;|\'|\"|%22).*(union|select|insert|drop|update|md5|benchmark|or|and|if)

Other changes

Optimized syntax, improved formatting.

Troubleshooting

If there is an error, remove the code and make a backup of your original .htaccess file (if you haven’t already done so). Investigate the URL for whichever page is blocked or not working, making note of any non-alphanumeric characters or anything else that looks unusual. With a good idea of what to look for, examine the 5G directives to see if anything looks similar. If so, try removing (or commenting out) the offending line (or characters) and see if that resolves the issue.

If that doesn’t work, further investigation is required, and there are numerous ways of going about it. Here is a good walkthrough of my halving method of isolating problematic code, which I recommend unless you have your own favorite way of troubleshooting ;)

Show support

If you benefit from my work with the 5G and would like to show support, consider buying a copy of my book, .htaccess made easy. You’ll get a complete guide to .htaccess, exclusive forum access, and a ton of awesome techniques for configuring, optimizing, and securing your site. Your generous support allows me to continue developing 5G/6G and other awesome resources for the community. Thank you!

Disclaimer

The 5G Firewall is provided “as-is”, with the intention of helping site administrators protect their sites against bad requests and other malicious activity. The code is open and free to use and modify as long as the first two credit lines remain intact. By using this code you assume all risk & responsibility for anything that happens, whether good or bad. In short, use wisely, test thoroughly, don’t sue me.

Learn more..

To learn more about the theory and development of the 5G Firewall, check out my articles on building the 3G, 4G and 5G Blacklist. The 6G beta article also contains some good information. And if all that’s not enough, a quick search for “blacklist” in the sidebar should also yield many results.

About the Author
Jeff Starr = Web Developer. Book Author. Secretly Important.
.htaccess made easy: Improve site performance and security.

91 responses to “5G Blacklist 2013”

  1. is this applicable for codeigniter framework?

  2. Mukesh Mali 2013/02/14 3:57 pm

    Thank You, I’m currently going through the same thing and links have appeared on my header to parked domains.

    From a marketing stand point, this could be devastating to your business.

    Great to see that Google takes care of their end very well,

    Success and Freedom!

  3. Nice update. Thanks Jeff.

  4. photocurio 2013/02/18 9:57 am

    Why isn’t playing.php written as playing.php? Sometimes dots are escaped, sometimes not?

    • Jeff Starr 2013/02/18 1:20 pm

      I thought it was safe to match playinga.php, playingb.php, and so forth, while other strings are more exact because of potential matches from the wildcard. Feel free to escape to get literal!

      • . is just a single wild-card character, right?

        So playing.php actually matches things like:
        – playing1php
        – playingaphp
        but not:
        – playing1.php
        – plyainga.php

      • Jeff Starr 2013/02/19 4:03 pm

        Correct, and it will also match a literal dot, like:

        playing.php

  5. Thank you for sharing this. First tests showed no problem.

  6. How would this do for Drupal websites?

    Any feedback on this?

  7. Nice work! :D

  8. Great piece of work. One slight hiccup I’ve come across with WordPress is that it appears to break the Press It bookmarklet. I’m assuming it’s because of the Javascript that’s passed in the URL but I’ve not had time to investigate and fix yet.

    I just wonder whether that match could allow the Press It URL but block other suspicious ones?

    • Jeff Starr 2013/02/20 4:44 pm

      Thanks for the feedback, Simon. Do you happen to know the Press It URL that’s getting caught? That may help refine the match to exclude the bookmarklet.

  9. Great work, thanks!

    Would it be possible to make this into a public Gist to make it easier to keep track of updates and to collaborate!?

    • Jeff Starr 2013/02/22 4:47 pm

      It’s something that I’ve thought about, and am still considering for the 6G Blacklist (still in beta). We’ll see how it goes!

  10. Rudy Pohl 2013/02/22 1:44 pm

    Hi Jeff:

    I manage several WordPress blogs and have already started using the 5G Blacklist on some of them.

    I also manage an old but very solid CGI-PERL driven content management system that produces no dynamic content but simple HTML pages as it output. It runs on a standard Apache server.

    Will the 5G Blacklist be helpful for this website?

    Thanks,
    Rudy

    • Jeff Starr 2013/02/22 4:43 pm

      Yes I think it would be helpful. 5G works by blocking bad requests at the HTTP/server level, using Apache modules/logic to filter incoming requests before responding with any content/pages. It shouldn’t matter how the pages are generated and/or if the content is dynamic or static, 5G wil help protect against malicious behavior.

  11. Ahmad Alfy 2013/02/24 3:06 am

    Can someone guide me why this is added?

    RedirectMatch 403 indonesia.htm

    What’s wrong with indonesia ? I’ve found a couple of 404 URLs on a website I am working on trying to access non existent pages redirected from .id domains. Any idea

    • Jeff Starr 2013/02/24 1:02 pm

      Yes, that string is included to block requests that include it. It’s a frequently scanned-for resource.

  12. Jay Miller 2013/02/25 2:17 pm

    I’ve not really had too much trouble using my current settings to discourage bad requests, but adding another set of security measures can’t really go wrong, especially with something other than a plugin which will slow down my blog. Thanks for the post!

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 »
Wizard’s SQL for WordPress: Over 300+ recipes! Check the Demo »
Thoughts
I live right next door to the absolute loudest car in town. And the owner loves to drive it.
8G Firewall now out of beta testing, ready for use on production sites.
It's all about that ad revenue baby.
Note to self: encrypting 500 GB of data on my iMac takes around 8 hours.
Getting back into things after a bit of a break. Currently 7° F outside. Chillz.
2024 is going to make 2020 look like a vacation. Prepare accordingly.
First snow of the year :)
Newsletter
Get news, updates, deals & tips via email.
Email kept private. Easy unsubscribe anytime.