Tag Archives: Drupal

How to protect your WordPress site using PHP Firewall plugin

This article explains how you can protect your WordPress site from attacks using my PHP Firewall WordPress plugin version 1.0.8.

This plugin is a commercial plugin, with one time fee, that it’s absolute worth it. It is not available as free plugin lite in WordPress.org. Only in my Software store. It is also available as PHP Firewall Drupal module.

Once you install the plugin, you click in Enable protection and the Firewall will start to detect attempts to find exploits in your server automatically, and will block the offending IPs.

If you Enable count of blocked requests you’ll see than in few minutes, the Firewall has blocked hundreds of attempts.

In this example, I activated the protection, and after some time it has automatically detected and blocked 118 offending IP Addresses, and has blocked 195 malevolent requests.

In 36 hours the number of blocked requests will get to thousands:

Enabling the count of blocked requests makes a small update in the database to increment the counter, it’s a very lightweight operation, but it is worth it to get an idea of how many malevolent requests the software is blocking. You can enable it for an hour, see how many bad requests you get, and disable it if you want.

Once you activate the protection you will start to see IP Addresses that have been blocked because they attempted a known exploit, and the IPs have been added to the list of Automatic offenders.

This function is known as WAF or Web Application Firewall.

Once an IP is detected as offender, it will get a 403 Forbidden answer from the Server immediately, and the precious resources from the server will be saved (CPU, Memory, Internet bandwidth).

If you want, you can delete the IP from the list to allow it access again (for example, if a colleague was doing a test).

As you see, you will get many IP from attackers blocked in a short window of time.

The reality is that bots are trying exploits against random IP Addresses all the times, and some times your server will go very slow because of all those bots trying to hack into your server, and your visitors will experience slow loading pages or even the server may crash due to all these bots activity. Also, depending on your Cloud provider, you may be paying for Internet Outgoing traffic that is consumed by bots.

So this plugin is a must have, in my opinion as Engineer. That’s why I created it. Because many people was asking for help.

But there are other types of abuse. For example, malicious bots will try to get access to your blog by doing requests with random passwords to wp-login.php every second.

The Firewall cannot block this route by default because is the route that legit users use to login to WordPress. But we have functionalities in the plugin to deal with these attacks (without having to analyse the web server logs, which is a task that System Administrators and Site Reliability Engineers do).

Activate Enable log of non blocked requests for analysis

This will record every allowed request (not the blocked ones), so we can analyse them.

Just scroll down, to Latest requests

As you can see there are IP Addresses that did a POST to /wp-login.php

That means that attempted to login in your site. So, they tried a password to hack your WordPress site.

Those IP Addresses are attempting to login every second or every two seconds.

These kind of attacks are not only bad, as they can get access to your site, they can also degrade the health of your database.

You can investigate where these IP’s come from doing a Whois search, or asking Google: whois 50.87.179.84

So, it’s a hosting from Bluehost / HostGator, a Cloud Provider. Servers from Cloud providers are typically hacked to try to hack other servers.

You can block the IP directly in the PHP Firewall using the custom rules, or as you can see in the information provider, this Cloud Provider has a NetRange / CIDR of 50.87.0.0/16.

A block /16 comprises 65,536 IP Addresses, so you’ll probably get attacks from many different IP’s in from that block. Instead of blocking just the IP that attacked your site, my approach is to block all the IP’s from that block.

So we add to Manual IP deny rules the block:

The reasoning about blocking all the 65,536 IP Addresses from the Cloud provider is that your WordPress site is probably a site for humans. You want humans to read your blog posts, or if it’s an e-Commerce site, you want to sell to humans. You don’t want bots to use the resources of your server or to try to hack your server. So blocking Cloud Provider’s IP ranges, seems like a good strategy.

If you are one of the few WordPress sites with third party integrations that need to be reached from Cloud providers, you can avoid denying those blocks of IP Addresses that your partners use.

We investigate the other IP:

And it’s the same case, so we also block the CIDR Block in the PHP Firewall.

A /22 block comprises 1,024 IP Addresses. So, with two lines in our firewall we have blocked potential malicious requests from 66,560 IP Addresses.

Obviously we cannot analize all the requests we get, but Firewall PHP plugin provides a very useful tool that will display the IP Addresses that did more request to our server in the last 24 hours.

Just click on Show IPs with most requests (last 24h)

The top 50 IP Addresses that performed more requests are displayed:

In this case, the first IP Address belongs to my own IP Address. Which makes sense because WordPress opened in the browser keeps doing requests to the server.

As I activated the log at 17:26:16 and it’s 21:44:10 in around 4 hours and 15 minutes I got an IP Addresses that did 264 requests.

The IP 134.209.183.0 has performed 264 requests that went through.

If I check the logs of the server I see that it was attempting to hack the server (trying user/password on wp-login.php)

grep "134.209.183.0" *.log

As you can see, this IP was requesting 12 requests per second trying to hack into /wp-login.php

And if we do the whois of this IP Address, it belongs to Digital Ocean:

So we block the entire block 134.209.176.0/20 in the PHP Firewall.

Now the server will block any request from the 4,096 in that block range and will not spend time and resources that are intended for your human visitors.

Most of the attacks come from Cloud providers. Normally are servers that got hacked, and they used those servers to try to hack other servers.

PHP Firewall provides great help in protecting your sites, specially if you don’t have a dedicated team of System Engineers that check the logs regularly, and block the offending IP Addresses in the firewalls.

After 12 hours we see more IP Addresses that made thousands of requests:

According to google those IP Addresses belong to Oracle Cloud:

So, we block the CIDR Block: 137.23.0.0/16 (which will block the two offending IP Addresses, as they form part of that block)

In the latest requests we can see how are new IP Addresses scanning for authors in order to try to attempt logins:

As you can see this IP Address is doing 10 requests in the same second trying passwords (POST to /wp-login.php) in order to attempt to hack the WordPress site.

We do a whois search to see who is the owner of that IP Address:

Is from DigitalOcean, the Cloud Provider. We block all the Netblock 139.59.0.0/16

We see a new IP attacking the server, it is attempting two connections per second POST to /xmlrpc.php which tries to perform actions on the site. xmlrpc.php is a legit mechanism from WordPress, for example to register pingbacks, so it is not blocked by default. But hackers use xmlrpc.php to try thousands of passwords at once without passing by the login screen.

If you do not use older mobile apps or specific remote publishing tools that rely on it you sholud block xmlrpc.php

The whois shows that many attacks come from this provider:

The site AbuseIPDB flags that IP as an attacker with more than 5,000 reports: https://www.abuseipdb.com/check/78.142.18.40

We can block the 256 IP Addresses of the class C, so: 78.142.18.0/24

We will also block the requests to /xmlrpc.php using Custom URL patterns:

Later, we see that there are more IPs attacking trying to abuse wp-login.php so we will block them:

We check the IP that is doing so many attempts to hack requesting wp-login.php

And all the range has been flagged for automated malicious activity and brute-force attempts

So we block all the 256 IP (class C) 93.152.221.0/24.

Two days later I check the IPs doing more requests:

I looked at the logs what requests was doing the first IP:

All were attempts to hack the site through /wp-login.php

We check what kind of IP is this, and it’s from a Cloud provider:

So we block the range 141.98.11.0/24 in IP Firewall.

If you have SSH to the server you can block it in the firewall.

For Ubuntu, with ufw that is:

sudo ufw insert 1 deny from 141.98.11.0/24 to any

A video of using WordPress PHP Firewall v. 1.1.0:

PHP Firewall WordPress plugin is a great help, as it blocks most of the attacks automatically, and offers you tools to detect the IPs that do more requests, so you can block them (or the entire range) easily, and to track the latest requests and export them.

Also, the price of the plugin is one time fee per site. Not a recurring payment.

There is also PHP Firewall Drupal module and a PrestaShop module.

If you want to acquire the Firewall rules that we have been collecting over the years, you can also buy the Firewall rules of Cloud providers from which we received attacks. These can be applied to any Firewall software, for instance Ubuntu ufw, or to my plugin/modules.

Stopping a BitTorrent DDoS attack

After all the success about the article stopping an XMLRPC to WordPress site attack and thanks messages (I actually helped a company that was being thrown down every day and asked me for help) it’s the moment to explain how to stop an attack much more heavily in evilness.

The first sign I saw was that the server was more and more slower, what is nearly impossible as I setup a very good server, and it has a lot of good development techniques to not having bottlenecks.

I looked at the server and I saw like 3,000 SYN_SENT packets. Apparently we were under a SYN Flood attack.

blog-carlesmateo-com-atack-to-the-web-2015-high-load-blacknetstat revealed more than 6k different ip addresses connecting to the Server.

Server had only 30 GB of RAM so, and started to be full, with more and more connections, and so more Apache processes to respond to the real users fast it was clear that it was going to struggle.

I improved the configuration of the Apache so the Server would be able to handle much more connections with less memory consumption and overhead, added some enhancements for blocking SYN Flood attacks, and restarted the Apache Server.

I reduced greatly the scope of the attacks but I knew that it would only be being worst. I was buying time while not disrupting the functioning of the website.

The next hours the attacks increased to having around 7,500 concurrent connections simultaneously. The memory was reaching its limits, so I decided it was time to upgrade the instance. I doubled the memory and added much more cores, to 36, by using one of the newest Amazon c4.8xlarge.

blog-carlesmateo-com-heavy-load-with-c4-8xlarge-black

The good thing about Cloud is that you pay for the time you use the resources. So when the waters calm down again, I’m able to reduce the size of the instance and save some hundreds to the company.

I knew it was a matter of time. The server was stabilized at using 40 GB out of the 60 GB but I knew the pirates will keep trying to shutdown the service.

Once the SYN Flood was stopped and I was sure that the service was safe for a while, I was checking the logs to see if I can detect a pattern among the attacks. I did.

attacks-access-log-bittorrent

Most request that we were receiving where to a file called announce.php that obviously does not exist in the server, and so it was returning 404 error.

The user agent reported in many cases BitTorrent, or Torrent compatible product, and the url sending a hash, uploaded, downloaded, left… so I realized that somehow my Server was targeted by a Torrent attack, where they indicated that the Server was a Torrent tracker.

As the .htacess in frameworks like Laravel, Catalonia Framework… and CMS like WordPress, Joomla, ezpublish… try to read the file from filesystem and if it doesn’t exist index.php is served, then as first action I created a file /announce.php that simple did an exit();

Sample .htaccess from Laravel:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes...
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Sample code for announce.php would be like:

<?php
/**
 * Creator: Carles Mateo
 * Date: 2015-01-21 Time: 09:39
 */

// A cheap way to stop an attack based on requesting this file
http_response_code(406);
exit();

The response_code 406 was an attemp to see if the BitTorrent clients were sensible to headers and stop. But they didn’t.

With with simple addition of announce.php , with exit(), I achieved reducing the load on the Server from 90% to 40% in just one second.

The reason why a not found page was causing so many damage was that as the 404 error page from the Server is personalized, and offers alternative results (assuming the product you was looking for is no longer available), and before displaying all the Framework is loaded and the routes are checked to see if the url fits and so has some process to be done in the PHP side (it takes 100 ms to reply, is not much, but it was not necessary to waste so much CPU), even being very optimized, every single not found url was causing certain process and CPU waste. Since the attack had more than 7,000 different ip’s simultaneously coming to the Server it would be somewhat a problem at certain point and start returning 500 errors to the customers.

The logs were also showing other patterns, for example:

announce?info_hash…

So without the PHP extension. Those kind of requests would not go through my wall file announce.php but though index.php (as .htaccess tells what is not found is directed there).

I could change the .htaccess to send those requests to hell, but I wanted a more definitive solution, something that would prevent the Server from wasting CPU and the Servers to being able to resist an attack x1000 times harder.

At the end the common pattern was that the BitTorrent clients were requesting via GET a parameter called info_hash, so I blocked through there all the request.

I wrote this small program, and added it to index.php

// Patch urgency Carles to stop an attack based on Torrent
// http://blog.carlesmateo.com
if (isset($_GET['info_hash'])) {

    // In case you use CDN, proxy, or load balancer
    $s_ip_proxy = '';

    $s_ip_address = $_SERVER['REMOTE_ADDR'];


    // Warning if you use a CDN, a proxy server or a load balancer do not add the ip to the blacklisted
    if ($s_ip_proxy == '' || ($s_ip_proxy != '' && $s_ip_address != $s_ip_proxy)) {
        $s_date = date('Y-m-d');

        $s_ip_log_file = '/tmp/ip-to-blacklist-'.$s_date.'.log';
        file_put_contents($s_ip_log_file, $s_ip_address."\n", FILE_APPEND | LOCK_EX);
    }


    // 406 means 'Not Acceptable'
    http_response_code(406);
    exit();
}

 

Please note, this code can be added to any Software like Zend Framework, Symfony, Catalonia Framework, Joomla, WordPress, Drupal, ezpublish, Magento… just add those lines at the beginning of the public/index.php just before the action of the Framework starts. Only be careful that after a core update, you’ll have to reapply it.

After that I deleted the no-longer-needed announced.php

What the program does is, if you don’t have defined a proxy/CDN ip, to write the ip connecting with the Torrent request pattern to a log file called for example:

/tmp/ip-to-blacklist-2015-01-23.log

And also exit(), so stopping the execution and saving many CPU cycles.

The idea of the final date is to blacklist the ip’s only for 24 hours as we later will see.

With this I achieved reducing the CPU consumption to around 5-15% of CPU.

Then, there is the other part of stopping the attack, that is a bash program, that can be run from command line or added to cron to be launched, depending on the volume of the attacks, every 5 minutes, or every hour.

blog-carlesmateo-com-blocking-traffick-black

ip_blacklist.sh

#!/bin/bash
# Ip blacklister by Carles Mateo
s_DATE=$(date +%Y-%m-%d)
s_FILE=/tmp/ip-to-blacklist-$s_DATE.log
s_FILE_UNIQUE=/tmp/ip-to-blacklist-$s_DATE-unique.log
cat $s_FILE | sort | uniq > $s_FILE_UNIQUE

echo "Counting the ip addresses to block in $s_FILE_UNIQUE"
cat $s_FILE_UNIQUE | wc -l

sleep 3
# We clear the iptables rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

# To list the rules sudo iptables -L
# /sbin/iptables -L INPUT -v -n
# Enable ssh for all (you can add a Firewall at Cloud provider level or enstrict the rule to your ip)
sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT

for s_ip_address in `cat $s_FILE_UNIQUE`
do
    echo "Blocking traffic from $s_ip_address"
    sudo iptables -A INPUT -s $s_ip_address -p tcp --destination-port 80 -j DROP
    sudo iptables -A INPUT -s $s_ip_address -p tcp --destination-port 443 -j DROP
done

# Ensure Accept traffic on Port 80 (HTTP) and 443 (HTTPS)
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# To block the rest
# sudo iptables -A INPUT -j DROP

# User iptables -save and iptables -restore to make this changes permanent
# sudo sh -c "iptables-save > /etc/iptables.rules"
# sudo pre-up iptables-restore < /etc/iptables.rules
# https://help.ubuntu.com/community/IptablesHowTo

This scripts gets the list of ip’s addresses, gets the list of unique ip’s into another file, and then makes a loop and adds all of them to the iptables, the Firewall from Linux, and blocks them for accessing the web at port 80 (http) or 443 (https, ssl). You can block all the ports also if you want for those ip’s.

With this CPU use went to 0%.

Note: One of my colleagues, a wonderful SysAdmin at Ackstorm ISP, points that some of you may prefer using REJECT instead of DROP. An interesting conversation on serverfault about this.

After fixing the problem I looked over the Internet to locate any people reporting attacks like what I suffered. The most interesting I found was this article: BotTorrent: Misusing BitTorrent to Launch DDoS Attacks, from University of California, Irvine. (local copy on this website BotTorrent)

Basically any site on the Internet can be attacked at a large scale, as every user downloading Torrent will try to connect to the innocent Server to inform of the progress of the down/upload. If this attack is performed with hundreds of files, the attack means hundreds of thousands of ip’s connecting to the Server… the server will run out of connections, or memory, or bandwidth will be full from the bad traffic.

I saw that the attackers were using porno files that were highly downloaded and apparently telling the Torrent network that our Server was a Torrent tracker, so corroborating my hypothesis all the people downloading Torrents were sending updates to our Server, believing that our Server was a tracker. A trick from the sad pirates.

Some people, business users, asked me who could be interested in injuring other’s servers or disrupting other’s businesses without any immediate gain (like controlling your Servers to send Spam).

I told:

  • Competitors that hate you because you’re successful and want to disrupt your business (they pay to the pirates for doing attacks. I’ve helped companies that were let down by those pirates)
  • Investors that may want to buy you at a cheaper price (after badly trolling you for a week or two)
  • False “security” companies that will offer their services “casually” when you most need them and charge a high bill
  • Pirates that want to extort you

So bad people that instead that using their talent to create, just destroy and act bad being evil to others.

In other cases could be bad luck to have been assigned an Ip that previously had a Torrent tracker, it has not much sense for the Cloud as it is expensive, but it has that a Server with that ip was hacked and used as tracked for a while.

Also governments could be so wanting to disrupt services (like torrent) by clumsy redirecting dns to random ip’s, or entertainment companies trying to shutdown Torrent trackers could try to poison dns to stop users from using Bittorrent.

 

See the definitive solution in the next article.