codeling / bfstop

Brute Force Stop Plugin (for Joomla!)
https://bfstop.bfroehler.info
GNU General Public License v3.0
36 stars 22 forks source link

Allow using .htaccess for blocking #74

Closed codeling closed 9 years ago

codeling commented 10 years ago

It was suggested that blocking via .htaccess instead of blocking via database could be highly advantageous in terms of performance.

This would have to be an optional alternative of course, since not every environment running Joomla! will allow blocking htaccess directives.

richardm75 commented 10 years ago

Using .htaccess will slightly improve performance. But I use nginx for Joomla sites wherever possible so it will not help me. It is also seems a bit tricky to me unless you parse the existing .htaccess file and understand the contents. What if there is an "Allow from all" directive already in there? You have to put your "Deny from 1.2.3.4" before that. And there might already be "Order" directives that defeat your additions. The .htaccess file might gain extra manual additions to sift through when you try to delete a previously added "deny". Of course it can be done, but it sounds a bit tough to me to ensure that your "Deny from" will always work as intended. On the other hand you could just append a "Deny from 1.2.3.4" on the end and hope for the best. Then continue to do the block in Joomla as well.in case the .htaccess didn't work. Just thinking out loud . . .

uncoda commented 10 years ago

richardm75 -

Totally agree with you on the implementation details, you would be using a flat file (.htaccess) as if it is a database, very messy and error prone. Plus only works on Apache.

But I would disagree on performance. I have dozens of sites running joomla (with Brute Force Stop installed) , and random brute force attacks have regularly brought down those sites because the hosting service shuts down a site that is using up too many resources (cpu) and sends me a message that it has shut down the site for an hour. I hacked Brute Force Stop with a tiny three line alteration that just puts a "deny from" at the end of the htaccess file, and it has worked really well for me. I have watched a site being attacked in realtime by three different ip addresses with my enhancement, and the site never was not shut down by the hosting service for excess resource usage - even after a day of continuous attacks by those ips. Before my hack , an attack from just one ip would trigger the resource blocking in less than an hour. My hosting service is totally PCI compliant and is very strict about security on their servers, so I had to get creative.

It seems to me, once a "deny from" statement is in .htaccess , the cost of Apache to reply to the attacker is very very small, I think it only sends back a header , because logs show that 0 bytes are transferred back to the ip that requested it. When a normal request for administrator/index.php login is sent , I would imagine that at least a dozen or more php files have to be loaded, parsed and evaluated by apache (and the database queried) before Joomla even hands it off to Brute Force Stop to check the database for an ip that is banned. And only then is the page with the login error sent back to the requester. So the comparative costs could be on the order of 10 , but I am just guessing, I would love to do a real world performance test.

The difference is small for a human browser because no one can click that fast, but the bot scripts I have encountered make numerous request a second, and don't even wait for a reply, they keep hammering the server and wait until they hit the right combo. Setting the delay on BFS has no affect because they don't wait for a reply, they will even simultaneously attack from numerous ip addresses.

So, although I agree that undoing a "deny from" is problematic , my nasty hack has solved a most difficult problem for me, and saved me lots of time and phone calls from clients who wonder why their site is down. I really don't care if the ban on the ip is permanent, 99.9% of the time it is from a malicious agent, and a locked out client will just call or email me if there is a problem. Granted , the sites I administer have few users that log in, so on a busy forum site the situation is different.

Of course I am selfish, and merely want something like what I did built into BFS , so I don't have to manually insert it when I install or upgrade. I totally understand that it may not be suitable for production code because of the implementation issues. But it seems that a "nuke" setting (with a permanent ban on the ip at htaccess) could be added in with the caveat to the user that they would have to manually undo it, is a doable solution. Of course, you guys have to code and maintain it, so easy for me to say...

richardm75 commented 10 years ago

I don't have your experience about performance gains. On balance though I think it is worth implementing because so many people use Joomla in a hosted environment using apache with .htaccess (e.g. GoDaddy, 1and1, webhostinghub, etc.) Yesterday we received an email from our hosting company for one site complaining about excess resource usage. The site was under a brute force attack (without bfstop, whoops!). Their recommendation was to add "Deny from" to .htaccess. Luckily we did that before they blocked us. Because we were adding it manually we could ensure that it was put into a position in the file that worked properly. That's the trick. So, give it a try, hope there isn't an "Allow from all" somewhere higher in .htaccess, and continue to do it always in bfstop as fall-back. My nginx sites are on a VPS, so I have enough control to add the equivalent blocking manually into nginx.conf. Or I might put the block into the iptables firewall. That's even better. The bfstop emails will trigger my action there. It's a pity that action won't be automated, but at least with bfstop I'll know to do something.

tgv604 commented 10 years ago

I'd like to vote for this improvement. It's super great that bad guys won't pick a password but they still are able to a) quickly consume all bandwidth allowance of an account -- happened to our client once, b) slow down the server considerably -- also happened to another few.

Just fyi, there's a plugin for wordpress that deals with .htaccess this way -- http://wordpress.org/plugins/brute-force-login-protection/ -- however it managed to corrupt the .htaccess file once, probably due to wicked amount of collected IPs..

Thanks!

codeling commented 9 years ago

Basic functionality implemented with commit 1874878b3673f21840f539e34d90b139ea488cb5 . Did some load tests with JMeter as well, and it looks very promising regarding performance boost: 5 threads / repetition until stable throughput established. plain joomla: 28/sec bfstop blocking (via db): 30/sec htaccess blocking: 1800/sec (tested on my slow development server machine, an Atom D520).

Note: Editing/Removing is not yet implemented. Will create a separate issue for this. Note 2: Thanks @tgv604 for your comment. Will have to take special care to avoid concurrency issues

codeling commented 9 years ago

@jpkleemans I'd love to use your .htaccess blocking code for this! Since it's GPL'ed I guess it should be fine, but I thought I'd ask anyway - are you fine with that ;)? You will of course be properly referenced. Thanks in advance!

jpkleemans commented 9 years ago

That's fine! Thanks for asking. Good luck with your plugin! :+1:

SactoBob commented 9 years ago

Am I missing something or does this code basically just append to the end of .htaccess? So these entries will never time out? This works as a quick-fix, but the prefered method would be to keep track of .htaccess changes and rewrite it as others mention.

Also from my observation (and others), if you run Apache, this is definitely the way to go. I have several Wordpress sites that put captchas in the login, but when a bot hits this and never gives up the system load goes way up. I found a WP plugin that uses .htaccess to block and now the load sticks around .05 when being hit. I would recommend taking a look at that WordPress plugin as a model for your .htaccess rewrite code. What it does is put a Begin/End like tag line around it's modifications, rereads .htaccess strips the old Begin/End out and rewrites the new Begin/End always at the top of .htaccess. Here's a sample of that (It has several sections, I'm just showing the section that pertains to this thread):

AIOWPS_BASIC_HTACCESS_RULES_START

AIOWPS_IP_BLACKLIST_START

Order allow,deny Allow from all Deny from 209.126.70.184 Deny from 217.8.245.128 Deny from 87.195.107.217

AIOWPS_IP_BLACKLIST_END

END All In One WP Security

The normal .htaccess code then follows this. I checked the code's license and it is GPL, so possibly this is something that can be used. It'll allow you to observed whitelist/blacklist and real time adds and expiration times too as you basically just rewrite .htaccess whenever one of those events kick in.

Plugin home page: https://www.tipsandtricks-hq.com/wordpress-security-and-firewall-plugin

Everything to write .htaccess looks to be self-contained in a class called AIOWPSecurity_Utility_Htaccess in the file /classes/wp-security-utility-htaccess.php under the plugin's directory. There's lots of extra stuff, but I'm sure the concept and the code can be stripped down to just the basics that are needed. If you are short of time, I'm willing to help out with this.

It's worth taking a look at some of the other options this plugins does too, such as writing rules to block access to .htaccess/wp-config.php/debug files/etc.

codeling commented 9 years ago

Haven't checked in detail yet but what you mention might be the same that I linked to above, and yes the plan for the next release is to use the class from there or sth. Similar. Thanks for the pointers!

SactoBob commented 9 years ago

Ah, I missed the link. I've actually used that plug-in as well for some of my other WordPress sites, pretty much the same concept. One or the other should be fine and a great improvement to bfstop for sure!

jpkleemans commented 8 years ago

Hi @codeling, I've created a package on GitHub for .htaccess blocking with PHP. See https://github.com/jpkleemans/htaccess-firewall. It has better code, and is much better tested then the current Htaccess class in my WP plugin. Maybe you can use it for your plugin. Feedback is always welcome!

codeling commented 8 years ago

@jpkleemans sounds great, I hope to have a chance to test this in the next few days!