Http Hobo

Another blog with web-development tips’n’tricks. | About me

4 steps to secure Wordpress installation on a VPS server

I’m not a huge fan of Worpdress. It’s creators publish security patches and updates so frequently, so every blog owner should hire a system administrator to take care of it. Not that security patches are bad, bad is the fact that so many of them are needed. However, having been watching over my wife’s blog for three years already, I’ve got some recipes on how to secure it and not have a permanent headache about it’s security.

Note: this instruction is for those who knows Linux command line basics.
Another note: My examples are compatible with Ubuntu 16.04.
One more note: Besides Apache + PHP + MySQL I use Nginx as a reverse proxy. It serves static files and provides some functionality which is to be mentioned in this post.

1. Set up correct directory rights

Wordpress has automatic updates for the core and plugins – it looks like a nice feature, but if it works you are in danger. Here is why – that means that your web-server (server software handling requests and sending responses) has rights to modify files in your blog. It means that if somebody will get access to the web-server (through some of countless Wordpress holes), he will be able to modify blog files injecting there malicious code. The only writeable directory for Wordpress should be uploads.

Here is what I do to secure directories:

# 1. Set my user as an owner, and www-data as a group of all the directories and files:
sudo chown george:www-data /my/wordpress/installation -R

# 2. Set directories mode to 755, and files to 644  (read for all, write for owner):
find /my/wordpress/installation -type d -exec chmod 755 {} \;
> find /my/wordpress/installation -type f -exec chmod 644 {} \;

# 3. Set upload directory and it's subfolders mode to 775, and files to 664 (read for all, write for owner and group):
> chmod 775 /my/wordpress/installation/uploads
> find /my/wordpress/installation/uploads -type d -exec chmod 775 {} \;
> find /my/wordpress/installation/uploads -type f -exec chmod 664 {} \;

2. Deny execution of PHP files in directories not supposed to be having PHP files

One of the most commonly used approaches to hack Wordpress I’ve ever seen was attempt to upload some PHP file to uploads directory and run it from there. Besides having correct directory rights, it wouldn’t hurt to deny Apache (or any other web-server) executing PHP files in some certain directories. Here is an example for Apache virtual host:

<Directory ~ "/my/wordpress/installation/(wp-content/uploads)/">
  <Files "*.php">
    Require all denied

Probably there is a way to do this in .htaccess file to make this solution more portable – I haven’t checked.

3. Set up protection against DDoS and bruteforce attacks.

Wordpress’ weak spots are:

  1. wp-login.php page
  2. xmlrpc.php file
    I’ve experienced lots of DDoS attacks on my installation, and logs always show these two files to be a target.

First thing we would do – add another authentication layer to Wordpress. It would be HTTP authorization for wp-login.php file. I use Apache as a web-server and set authorization right in the virtual host:

<Directory /my/wordpress/installation/>
  # Some directory settings

  <Files "wp-login.php">
    AuthType basic
    AuthName "Please enter your username and password"
    AuthUserFile /etc/.htpasswd
    Require valid-user

File /etc/.htpasswd should be created using htpasswd utility.

Now I slow down those who are trying to DDoS or bruteforce my Wordpress. I don’t know how to limit number of requests to a particular file in Apache, but as I sad earlier – I use Nginx which has “Rate limit” functionality, so I added the following settings to it’s configuration files:

# This goes into nginx config (/etc/nginx.conf in my case) into http section. This line will define a zone which will limit requests to 1 per second, and zone's size is 10 Mb.
limit_req_zone $binary_remote_addr zone=mywordpress:10m rate=1r/s;

# This goes into virtual host under server section. All the requests to xmlrpc.php will be handled according to the zone rules, allowing a burst of 5 requests though.
location /xmlrpc.php {
  limit_req zone=mywordpress burst=5;
  include /etc/nginx/proxy_params;

location /wp-login.php {
  limit_req zone=mywordpress burst=5;
  include /etc/nginx/proxy_params;

What is wrong with xmlrpc.php file? Nothing except it’s commonly used for DDoS attacks. Easier approach would be to just deny access to it, but it’s not a solution in case you want to use some wordpress client. My solution should be better.

4. Addition: protect your phpmyadmin if you have any

I’ve seen tons of access log records showing attempts to find my phpmyadmin – they knocked to /pma, /phpmyadmin, /admin and many other links. So in order to secure it too, I do the following:

  1. Don’t use /phpmyadmin and any other obvious link for PhpMyAdmin. Better use something you can remember, but not related to “php”, “my” and “admin” words, e. g. /blablabla, /ilovemydatabase, /houston.
  2. Bind HTTP authorization to it too. Example is above.

Of course there is more you can do about your wordpress security and safety. I’m not specializing in server administration, but above are recipes which I have been using for some time and having no problems so far. If you have something to add or improve, I would be happy to see you comment.

P.S.: I don’t work with Wordpress a lot. It’s a coincidence having already two posts about Wordpress in my blog. :)

Update 22.11.2017: I thought that PHP files within wp-includes directory are never called directly, and only being included into main script. That’s not correct, for example TinyMCE does a direct call. Thus wp-includes directory should not be blocked in step (2).

2017   security   wordpress