We talked about blocking WordPress XML-RPC and preventing DDoS attacks on Cloud IaaS. Our crime was talking about blocking WordPress XML-RPC Attack via PHP-WordPress way. The script kiddies were running the exploit on a shared server, possibly enjoying the access to the database, we probably harmed their way of spamming. Their outburst of anger on our servers did more bad. We faked as if we are not understanding the attacks. We collected a list of IP addresses. All IPs and instances are of Amazon.
WordPress XML-RPC Attack : The Fake PHP5-FPM Error Part
A newbie will think the resulting problem as problem related to Nginx PHP5-FPM unix socket or some other stuffs. The errors are same.
These Attacks Can Bring DDoS Resulting in Random 502 PHP5-FPM Errors on Nginx Server or Can Make the Database Down. Here is Fix. But we need to tell you how to diagnose it. In the case of a shared server, non-key based virtual router-less web host, it is not difficult to hack the whole database.
---
Not all are using HP Cloud or IBM.
If we had not faked as “we are not aware”, we could not collect any data. In very short, unless you check the Nginx access log, Error log, MySQL log; unless the PHP5-FPM Error is arriving – it will be a typical Nginx-PHP5-FPM Error with a moron like a link towards Nginx’s website for checking the log. When you will try to flush the cache manually or access the admin area – you’ll face the white page of Nginx declaring an error. You’ll think that possibly you have the wrong configuration of PHP5-FPM or there is an issue with the resource. You can give a 16GB server to face and increase the PHP memory to 50% of it – it will die sooner, exactly like a 4GB server.
WordPress XML-RPC Attack : The Fake PHP5-FPM Error Part
For a normal Nginx-PHP5 setup on Deb GNU/Linux ( read Ubuntu server and Nginx from repo ), if we cd to /var/log/nginx
and use awk to list the number of access against the HTTP code against the access.log
file, in this way :
1 2 | cd /var/log/nginx awk '{print $9}' access.log | sort | uniq -c | sort -rn |
if I get this kind of result :
1 2 3 4 5 6 | 832123 502 339996 499 166366 403 25699 301 361 404 305 200 |
it simply points – 502 errors are most common on the server. 499 error code is for a POST from another server, take it as 502. A server is designed for serving pages with 200 HTTP code.
WordPress XML-RPC Attack : Log Analysis
It becomes easier to directly do a cat over the error file :
1 | cat /var/log/nginx/error.log |
I will get some logs. The log will bear this kind of error, it is a variant not :
1 | [error] 3239#0: *15188 connect() to unix:/var/run/php5-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 52.24.47.119, server: thecustomizewindows.com, request: "POST /xmlrpc.php HTTP/1.0", upstream: "fastcgi://unix:/var/run/php5-fpm.sock:", host: "xxx.xxx.xxx.xxx" |
That 52.24.47.119
is sending POST request to thecustomizewindows.com/xmlrpc.php
in this way :
1 | curl https://thecustomizewindows.com/xmlrpc.php -d '<?xml version="1.0" encoding="iso-8859-1"?><methodCall><methodName>pingback.ping</methodName><params><param><value><string>http://abc.com/hello-world/</string></value></param><param><value><string>http://xyz.com/hello-world/</string></value></param></params></methodCall>' |
NORMALLY, none sends POST requests to others’ servers without prior permission. We send GET requests, not POST – if you are a new user to server administration.
SO, EVEN before getting 502, 499, 301 etc. errors, we can do a cat on access.log
file :
1 2 3 | cat access.log | grep 52.24.47.119 ## or if IP unknown cat access.log | grep /xmlrpc.php |
we will get a huge log with this type of info :
1 | 54.69.229.22 - - [28/Jul/2015:20:20:20 -0500] "POST /xmlrpc.php HTTP/1.0" 499 0 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; http://www.google.com/bot.html)" |
there is no http://www.google.com/bot.html
at present. Google has hugely informative pages on Google bot and IPs :
1 | https://support.google.com/webmasters/answer/80553 |
Google only sends bots from googlebot.com
and google.com
. If you run the top
command during the attacks, there will be high CPU usage plus higher RAM usage. WordPress will tend to become slower, even if does not fail. As a screening test, if we run this command over the file /var/log/nginx/access.log
:
1 2 | cd /var/log/nginx/ cat access.log | grep xmlrpc | awk '{print $1}' | sort | uniq | wc -l |
we will get a numerical value. If it is, suppose 157, definitely the server is under attack – that is the number of unique IPs! We can run this command :
1 2 | cd /var/log/nginx/ cat access.log | grep xmlrpc | awk '{print $1}' | sort | uniq |
We will get the list of those (for example) 157 IPs. We can create a text file out of it and put it on GitHub for easy crawl by Google when someone will search for the IPs on Google search, see here – BlackListed IPs for running XML RPC attacks.
WordPress XML-RPC Attack : Solving the Issue
If you get the IP from the log it’s great, as we have :
1 2 3 4 5 | 52.24.47.119 54.69.228.145 54.69.229.22 52.10.165.55 52.25.199.249 |
As they are already known, we technically should use a firewall to block plus ban via Nginx. For Nginx, we can add a include directive in the way we described before how to use include directive, add one line on /etc/nginx/nginx.conf
:
1 | include /etc/nginx/knownhackers.conf; |
then create a knownhackers.conf
file in /etc/nginx/
:
1 | nano /etc/nginx/knownhackers.conf |
against the above IPs we will add content on knownhackers.conf
like this :
1 2 3 4 5 | deny 52.24.47.119; deny 54.69.228.145; deny 54.69.229.22; deny 52.10.165.55; deny 52.25.199.249; |
then run a configtest with nginx -t
and restart nginx with service nginx restart
. We should also use some firewall to fully reject the IPs :
1 2 | # one example, should be repeated for all the IPs iptables -A INPUT -s 52.24.47.119 -j DROP |
BUT, where is the promise that hackers will not use a different IP? That is why, on /etc/nginx/sites-available/default
or equivalent vHost file, we will add this within the server { }
block :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | location ~ xmlrpc\.php { deny all; allow 127.0.0.0/24; allow ::1/128; allow 66.135.32.0/19; allow 66.155.0.0/18; allow 69.174.240.0/20; allow 72.232.0.0/17; allow 76.74.248.0/21; allow 192.0.64.0/18; allow 198.181.116.0/22; allow 207.198.64.0/18; allow 209.15.0.0/16; allow 216.151.208.0/20; } |
allow
IPs are whitelisted and related to WordPress. We have not discovered them – we found on website named codepie.org
. Then run a configtest with nginx -t
and restart nginx with service nginx restart
. If you are not liking to allow the WordPress related IP, simply use :
1 2 3 4 | location ~ xmlrpc\.php { deny all; allow 127.0.0.0/24; } |
If the server has both port 443 and port 80, we would add the directive in both places to avoid a minimal chance of escaping 301 redirects from port 80 to port 443. Finally, we need to add some extra kinds of stuff on either Child Theme’s functions.php file or its replace plugin (about which we wrote here to avoid hundreds of snippets on Child Theme’s functions.php). The snippet we will add is :
1 2 3 4 5 | add_filter( 'xmlrpc_methods', 'remove_xmlrpc_pingback_ping' ); function remove_xmlrpc_pingback_ping( $methods ) { unset( $methods['pingback.ping'] ); return $methods; } ; |
Finally, disable pingback, trackback from the WordPress admin panel.
WordPress XML-RPC Attack : Check MySQL Log
The main reason for running the attack is usually to get backlinks. It is possible to push a bad post with other methods of hacking WordPress. Those IP related instances are a kid in front of bigger powerful servers. Probably we are too good for those who never deserve kindness. We should check the MySQL log for the last commands/queries ran on it :
1 | cat ~/.mysql_history |
If you see odd kinds of stuff (like the push of hyperlinks), you should find database related forum and terminate the pregnancy. ~/.mysql_history
does not depend on your settings on my.cnf
.
The IPs unless manually checked, can be victims as a part of Man in the Middle Attack.
Random PHP5-FPM Error is often misinterpreted as an error of configuration. For errors of configuration, your IP can trigger the error by just visiting a page or doing an action.
Finally, you should clear the log files using our described method, in this way :
1 | echo " " > /var/log/nginx/error.log |