Best security practices for WordPress installations

If you want to set up your own website but you are not an expert, you may have seen the word “Wordpress” spread. It is a CMS (Content Management System) to help in the the creation of a website. Basically, it facilitates creation and management by providing a ready-to-use interface. Now all you have to do is customize your site and write your articles! No need to write code (even if it is possible to search and modify manually) !

However, some features which can be dangerous for the security of your website are by default left enabled… There are simple ways to patch this and improve the security of a WordPress site. What follows is not purely technical, but some additional research may be needed to understand the whole picture. The purpose of this article is to group the various things to modify, the various techniques that I found on Internet in order to learn why this is dangerous, but especially how to be protected by simple modifications!

Context & State of the art

First, let’s set up a frame for this post with some figures. Wordpresss, it’s :

  • Almost 25% of websites and blog you can visit everyday
  • More than 70.000.000 blogs
  • 44.000 plugins
  • Available in 56 languages
  • 82.000.000 new posts every month !
In other words, it is currently an important part of the known web. It means that Wordpres websites are also the most targeted websites by malicious users, trying to steal information, break in... And unfortunately, in order to be as versatile as possible, a WordPress installation leaves features enabled...

Limit information leak

One of the most important things as an attacker is to get as much information about your target as possible. There are various simple ways to retrieve all kinds of information and it turns out that WordPress lets some things pass at this level. It is therefore important to know these methods and how to correct these problems.

Wordpress version

When searching for information on a website, one of the first information sought is the version of the site. Indeed, it is not uncommon to find vulnerabilities in older versions, which explains the regular updates. Thus, finding the version of the WordPress site will guide an attacker to attack the website. By default, it is possible to find the version of a WordPress website. One of the easiest ways to get the version of a website in WordPress is to use RSS feeds, accessible directly from the URL https://monsite.com/feed. A little check in the source code of the page reveals the information.

wpharden_version_1

Removing this information is important. An effective solution for this is to modify one of the WordPress PHP files to add a small piece of code. This is the functions.php file available in the directory https://monsite.com/wp-includes/. We’ll add the following code.

// Remove WP version from feed
function remove_wp_version() {
return '';
}
add_filter('the_generator', 'remove_wp_version');

Thus, no more version leak trouble ! However, I would like to add something. It is necessary to focus on regular updates and to apply them if you can. These updates allow you to add content but also to patch vulnerabilities and so, to enforce your security.

robots.txt file

The robots.txt file is a public file used by the various robots that browse the internet to reference your website. As a public file, it is important to limit information, and especially useless information, because it can be seen by any user going on the page http://monsite.com/robots.txt. This file allows robots to specify what they should index and reference and what they should not.

As an example, here is the content of the robots.txt file for the site https://haax.fr.

wpharden_robots_1

“Disallow” clauses tell robots to not index what’s behind. So, I ask robots to not index my administration interface (wp-admin), the different PHP configuration files of the website, etc….

However, I ask them to index the content of /wp-content/uploads because it is the directory containing pictures of the different posts. Thus, pictures will be referenced on the various search engines and this blog will be found by users.

The interest of explicitly specifying to robots not to index certain parts of your site is to prevent anyone from coming across unwanted pages (for example, the page connecting to the administration area) simply with search engines…

To illustrate what I just said, here is an example of websites that let Google index their login page to the administration area. It doesn’t seem to be a lot, but it’s just making it easier for people with bad intentions….

wpharden_hidelogin_2

.htaccess file

The.htaccess file is a very important file for the security management of your website. It is located in the root folder of your website and allows you to set up different navigation rules that will be applied to each user who visits your site.

It is for example possible to force a redirection to a page, to prevent someone from accessing an area of the site, or simply deny access to some sensitive files.

It is therefore extremely important to prevent anyone from accessing this file. You can write a rule in your file that will prevent any user from accessing it. The following rule allows you to do this.

##Deny access to all .htaccess files
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>

So if someone tries to access the file, they will get the following result.

wpharden_htaccess_1

Users enumeration

WordPress works with an authoring system. It is indeed possible to see all the articles published by an author by going to the page /author/personname. However, by default, we do not know the users’s name.

As in most databases, WordPress works with a system of unique numbers called “id”, identifying each user. Thus, the first user created (and often the administrator..) has id 1. The second user has id 2, etc.

It is possible to list users by asking for example https://monsite.com?author=1. Thus, the user will be redirected to the corresponding /author/person. Various tools exist to automate the enumeration process, but this is not the topic of this post.

It is therefore important to prevent a potential attacker from being able to list users of your website, because if it happens, it means that the attacker already has connection information. All he has to do is to find the password…

An easy solution is to redirect every user who tries to list to the home page. Redirections can be made by rules placed in the .htaccess file of your website. The following rules correspond to this need:

##Avoid users enumeration and redirect to index
RewriteCond	%{REQUEST_URI}	!^/wp-admin [NC]
RewriteCond	%{QUERY_STRING}	author=\d
RewriteRule	(.*)		$1? [L,R=301]

##Redirect /author/
RedirectMatch 301 ^/author/ https://haax.fr/?

So if someone tries to list users of the website, they will automatically be redirected to the home page and will not have access to the information.

Useless installation files

Once your WordPress site is installed, some unnecessary files remain available on the website. It is important to identify the files to delete as they may reveal information to an attacker. The readme.html file is one of these files. This is a file in the root folder of your website explaining the procedure for installing a WordPress site, as well as other things not very useful. However, this file may also reveal the version of WordPress you are using. Thus, if your site is not up to date, it is possible that it presents known vulnerabilities. If an attacker becomes aware of this information, he can use one of these vulnerabilities against your website.

Here is an example of a website that did not delete the readme.html file.

wpharden_readme_1

We can see that this is a WordPress 3.0 website… A very old version, and therefore probably full of vulnerabilities. It is therefore important to delete this file. Once done, if someone tries to access the https://monsite.com/readme.html file, they will get the following result.

wpharden_readme_2

Directory Listing - Access to wp-includes folder

Always in order to limit the information leak as much as possible, it is important to control what is accessible. We have seen thanks to the file robots.txt that it is possible to forbid robots to reference some parts of a website. However, these areas are still fully accessible to anyone who fetches them manually… For example, the /wp-includes/ directory contains a whole bunch of configuration files.

So, if you try to access it manually and access is not restricted, you get the complete list of files.

wpharden_includes_2

Here again, it is possible to restrict access by writing a rule placed in the .htaccess file. We will simply deny any user access to the /wp-includes/ directory as well as the files present here.

##Block wp-includes folder and files
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php$ - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]

Thus, an attempt to access this directory now ends in failure.

wpharden_includes_3

WP-config.php

The wp-config.php file is one of the most important configuration files for your website. In particular, it contains the connection information to your database. It is imperative to block access to this file for any user coming from outside. Some researches on the internet and we find this kind of file in free access on some websites…

wpharden_config_1

Once again, the access restriction to this file can be done through a HTACCESS rule. We will simply specify that access to the file is forbidden, for everyone.

<files wp-config.php>
order allow,deny
deny from all
</files>

Result… Nothing!

wpharden_config_2

Limit intrusion risks

Hide the admin panel

By default, the login page to the wordpress administration area can be obtained through the following URL https://monsite.com/wp-admin

In concrete terms, this means that anyone can try to connect to your website with different login and passwords. An exposed administration interface is taking unnecessary risks. This is why it is important to change the default path to this interface.

Several solutions exist for this, but the easiest solution to implement is usin a plugin. Plugins such as WPS Hide Login allow you to simply modify the access URL to the administration area.

wpharden_hidelogin_2

XMLRPC.php file

Brute-force attacks are widespread on the Internet. The principle is very simple: you try to connect to a service by trying millions of possible login/password combinations and hoping to come across a good combination. The so-called XMLRPC attack is a known attack that allows an attacker to test several hundred login/password combinations on a WordPress site in a single request. By sending a large number of requests, the attacker has the possibility to test a very large number of combinations.

By default, any recent wordpress site is vulnerable to this attack, because the xmlrpc.php file is accessible to any user. To test if your site is vulnerable, nothing easier! Just try to access the file in your browser.

wpharden_xmlrpc_2

If the result is a blank page with the text “XML-RPC server accepts POST requests only.” then you’re vulnerable. You should know that XMLRPC is not there for nothing, it is possible that your site uses this functionality. It is advisable to check the use of this feature before turning it off.

However, if you do not use it, it is important to prevent access to this file. Several solutions exist for this. A simple solution is to add a rule to your site’s .htaccess file to prevent visitors from accessing the file.

The following rule can be added:

##Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
</Files>

Once modified, a query on the xmlrpc.php file should return this:

wpharden_xmlrpc_2

If this is the case, the file is no longer accessible, and therefore an attacker will no longer be able to exploit this vulnerability!

Limit login attempts

By default, WordPress allows a user to attempt to log in with an infinite number of usernames and passwords. We have the same problem as in the previous paragraph, the site is vulnerable to bruteforce attacks. Even if the site is no longer vulnerable via XMLRPC, the login interface remains accessible and a malicious person might try to attack your website through this way.

It is therefore important to limit the number of login attempts per user. Once again, a good solution can be to use a plugin. There are several ways to do this. It is then possible to customize the maximum number of attempts desired.

wpharden_limitlogin_1

Having different usernames and public names

By default, when you publish a post with Wordpress, the author’s name is displayed on the post. And by default, the author you publish with is also the Wordpress account username. Therefore, publishing a post reveals your user name, thus giving information to a potential attacker. Fortunately, it is possible to use a nickname for each account, allowing you to change the name publicly displayed on your articles.

wpharden_username_1

Final word

WordPress is a very interesting CMS, easy to learn and offering a multitude of features and possibilities. Undeniably, on the other hand, the system needs to be as versatile as possible to suit all uses. This implies default settings, values, files… Things that can endanger your website.

Taken individually, most of the points in this post are not extremely serious or compromising, but if you add them together, they can significantly weaken the security of your website. It is therefore important to know this kind of thing but also to remain active and attentive to what surrounds us, such as the discovery of vulnerabilities.

The password reuse threat Android Internet Box and Privacy - The iceberg summit