NGINX / Apache: Block Requests to PHP file (xmlrpc.php)

This is going to be a short post about how to block your webserver from serving a specific file.

WordPress comes with a file called xmlrpc.php which enables you to use their mobile App on self-hosted blogs or enables ping- and trackbacks. However, there is a bunch of bots out there that attempt to brute-force their way in and can produce either high load or actually present a security risk.

I have chosen to drop requests to that specific file because it was clogging up my access log. As soon as I switched to another server for some of my WordPress sites, like this one, requests to that file came flooding in multiple times per second.

The Sucuri Plugin enables this behaviour by default too if you are making the suggested changes to the .htaccess file and if you’re running Apache.

Dropping / Denying Requests with Nginx

The below nginx config is for WordPress with PHP-fpm without a lot of extra config.

# pretty vanilla nginx, php5-fpm and wordpress server block
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /var/www/your_directory;
    index index.php index.html index.htm;

    location / {
        # try_files $uri $uri/ =404;
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        root /usr/share/nginx/html;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location = /xmlrpc.php {
        deny all;
        access_log off;
        log_not_found off;
    }
}

The part that blocks the traffic to the xmlrpc.php is just the last bit:

location = /xmlrpc.php {
    deny all;
    access_log off;
    log_not_found off;
}

With that we explicitly deny access to it. Note that instead of using an explicit filename, you could as well use a wildcard like * or similar. Note that if you use a wildcard, you need to move that location block above the one that is applied to re rest of the PHP files in your nginx config.

Dropping / Denying Requests with Apache

Assuming you have something like the default .htaccess config for WordPress, you just need to add a small block to it.

In order to ignore a certain file from being served with the Apache server, just add the following snippet to your usual WordPress .htacces file:

<Files "xmlrpc.php">
Order Allow,Deny
Deny from all
</Files>

Summary

Denying files from being server or limiting the serving to certain IP addresses is a handy security and in some cases load decreasing measure. If you don’t want an entire directory served or if you have any super secret data, there are two much more important rules though:

  1. Don’t keep them on a web server.
  2. Don’t keep them in a directory that a web server serves.

Example Logs

Lastly, I have included a samle of what the logfile looks like, as you can see many of the requests come from different IP addresses to avoid getting IPs blacklisted:

Example logfile of what nginx was logging before I denied that file:

117.248.8.144 - - [18/Jun/2016:23:57:47 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
74.56.157.129 - - [19/Jun/2016:00:07:18 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
74.56.157.129 - - [19/Jun/2016:00:07:18 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
92.82.96.166 - - [19/Jun/2016:00:23:37 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
92.82.96.166 - - [19/Jun/2016:00:23:38 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
185.50.198.118 - - [19/Jun/2016:00:38:10 +0200] "POST /xmlrpc.php HTTP/1.0" 200 0 "-" "-"
24.131.247.86 - - [19/Jun/2016:01:15:57 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
176.74.124.211 - - [19/Jun/2016:01:44:00 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
176.74.124.211 - - [19/Jun/2016:01:44:00 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
31.176.215.205 - - [19/Jun/2016:01:44:48 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
31.176.215.205 - - [19/Jun/2016:01:44:48 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
200.86.189.3 - - [19/Jun/2016:02:13:22 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
200.86.189.3 - - [19/Jun/2016:02:13:23 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
124.104.232.93 - - [19/Jun/2016:02:14:59 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
124.104.232.93 - - [19/Jun/2016:02:14:59 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
112.198.75.254 - - [19/Jun/2016:02:29:18 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
112.198.75.254 - - [19/Jun/2016:02:29:18 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
72.172.183.35 - - [19/Jun/2016:02:36:52 +0200] "POST /xmlrpc.php HTTP/1.0" 200 0 "-" "-"
105.107.50.133 - - [19/Jun/2016:02:45:48 +0200] "POST /xmlrpc.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
105.107.50.133 - - [19/Jun/2016:02:45:48 +0200] "POST /xmlrpc.php HTTP/1.1" 200 31 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0"
58.11.7.158 - - [19/Jun/2016:03:27:17 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
58.11.7.158 - - [19/Jun/2016:03:27:18 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
176.106.59.51 - - [19/Jun/2016:04:09:59 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
176.106.59.51 - - [19/Jun/2016:04:09:59 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
179.52.126.202 - - [19/Jun/2016:04:12:51 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
179.52.126.202 - - [19/Jun/2016:04:12:52 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
36.71.65.253 - - [19/Jun/2016:04:33:50 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
36.71.65.253 - - [19/Jun/2016:04:33:51 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
120.29.66.136 - - [19/Jun/2016:04:56:01 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
120.29.66.136 - - [19/Jun/2016:04:56:01 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
83.61.73.164 - - [19/Jun/2016:05:09:02 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
83.61.73.164 - - [19/Jun/2016:05:09:02 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
200.120.200.63 - - [19/Jun/2016:05:16:57 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
200.120.200.63 - - [19/Jun/2016:05:16:57 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
117.203.166.74 - - [19/Jun/2016:05:50:01 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
117.203.166.74 - - [19/Jun/2016:05:50:02 +0200] "POST /xmlrpc.php HTTP/1.1" 200 5 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"

4 thoughts on “NGINX / Apache: Block Requests to PHP file (xmlrpc.php)”

  1. Thanks for sharing that especially the Nginx part. Also if you are using whm and have root access you can install Comodos mod security rule set which comes with protection for xmlrpc.php as well as login pages for WordPress and other popular CMS such as Drupla, Joomla etc.

    Pair that up with CSF for auto ip-bans when the rules are triggered and you have simple and very powerful solution that is server wide.

  2. Your remark about using a wildcard instead won’t work!
    The /xmlrpc.php location block is used because it is referring to a specific file/filesystem location.
    Regexes are however evaluated in the order they are defined.
    That is if you define a *rpc.php location where you have the /xmlrpc.php one, it will never fire because there’s already another regex matching in front of it.

  3. Fantastic article. Love the easy descriptive way to block access to xmlrpc.php from bots that blast as it. We’ve also IP restricted the file in .htaccess for even more protection.

Leave a Reply

Your email address will not be published. Required fields are marked *