WordPress security & hardening, the definitive guide

Last updated on January 26th, 2021 by Mark Grima. Filed under WordPress Security

Featured image *WordPress security*

WordPress is massively popular. Around every one in five sites on the Internet uses WordPress in some form. Be that to run a humble blog, or a multi-site Content Management System (CMS) or eCommerce site. As a result, it is no surprise that WordPress websites are a very popular target for both experienced hackers and script-kiddies alike.

The last thing any webmaster wants is to find out that their website has been hacked; maybe taken hostage and is part of a botnet, spreading malware, or partaking in Denial of Service (DoS) attacks. In this article we’ll be sharing a number of tips and strategies to help you harden your WordPress website.

Table of contents

Is WordPress secure?

This is a question many system administrators ask, and rightfully so. While WordPress is overall well-built and secure, it has a reputation for being prone to security vulnerabilities and not being “enterprise-grade”. That reputation is not exactly fair. More often than not, issues lie in WordPress being an incredibly popular software package which is easy to set up while taking security shortcuts. Which brings us to our first topic — plugins and themes.

Plugins and themes

The number one issue which plagues WordPress security is also what makes it incredibly popular. WordPress plugins and themes vary far and wide in terms of quality and safety. While a lot of work has been done by the WordPress team to help developers build more secure plugins and themes, they still remain a security nightmare. This can be noticed when using poorly maintained plugins, or plugins obtained from a sketchy source.

Before we continue discussing WordPress plugins and themes, let’s first understand what a WordPress plugin actually is. Plugins are simply custom PHP code that WordPress runs in order to extend WordPress’s functionality. For a more detailed and technical explanation refer to What are WordPress plugins.

Similarly, WordPress themes allow for the customization of the visual aspects of your WordPress site. From an attacker’s perspective, there is very little difference between the two since both can be abused to run malicious code.

Run less software

So how can you tell if a plugin is malicious or not? That’s a complicated question, but fortunately we have an answer for you. We have written about this in detail in how to choose the best WordPress plugin for your WordPress website.

Even though you make all the necessary research, there are also chances that the plugin might still be a security threat. So one of the ways to reduce your risk is to only run the software you absolutely need and trust. Before installing a new WordPress plugin ask yourself if you really need to install that plugin. Can a small code snippet in a site-specific plugin do the trick, or do you legitimately need a fully blown plugin?

Important — be very vigilant with code snippets you find on the Internet. Never use a piece of code unless you fully understand what it’s doing — just because it’s on StackOverflow, it doesn’t mean it’s safe to use.

If you have a genuine need to run a plugin, make sure it’s actively maintained and regularly updated as we explain in our guide. As a rule of thumb, the more downloads and recent updates the plugin or theme has indicates that it is in wide use and that it is being actively maintained by its authors. This does not mean that the plugin will never have a vulnerability. However, if a vulnerability is found, the developer will act quickly and issue a fix quickly.

Try to avoid plugins which don’t have many downloads and critically, do not have an active community and regular updates. If something hasn’t received an update within a year, it’s generally a red flag.

Observe the least privileged principle

WordPress does not need to use the MySQL root user to connect to its database. Nor does every WordPress user need to have the role of an administrator. Similarly, it’s not a good idea to run most programs as a privileged user, unless there is a specific reason to do so.

Security best practice always dictates for applications to always be given the least privileges possible that allow it to work properly, with any additional privileges disabled. This practice is commonly referred to as the principle of least privilege.

Let’s hypothetically assume WordPress is connecting to a database with a privileged user account. In the event of a WordPress plugin containing an SQL injection vulnerability, an attacker may be able to not only run SQL queries as an administrator, but in some cases they may even be able to execute operating system commands. If an attacker is successful in executing operating system commands, they may be able to carry out reconnaissance and escalate an attack further to other systems.

Running software with administrative privileges, or providing users with more access than necessary is asking for trouble. It goes against a tried-and-tested least privilege principle, since it allows an attacker to inflict more damage in the event of a security breach.

The good thing with WordPress is that is has a number of built-in roles, which you can use to assign different privileges to different users, depending on their requirements. We have written extensively about this in how to use WordPress user roles for improved WordPress security.

Update your WordPress plugins and themes

WordPress plugin and themes updates are important not just to benefit from new functionality and bug fixes, but also to patch security vulnerabilities. Both plugins and themes are easy to update within the WordPress interface.

Some commercial plugins will likely have their own mechanisms to keep plugins up to date, however, in most cases this is transparent to the users. Nonetheless, just make sure that whatever update system is being used, you keep your plugins and themes up to date.

Do not use ‘nulled’ WordPress plugins and themes

WordPress nulled plugins
WordPress makes use of the GPL1. Without going into much detail, the GPL license allows for anyone to freely distribute GPL-licensed software. This includes commercial/premium GPL-licensed WordPress themes and plugins. As such it may not be illegal to download a modified, usually referred to as nulled, premium theme or plugin and use it for free.

However, as you may have already guessed, aside from not supporting the plugin developer, you are very unlikely to receive updates for nulled plugins. What’s more, you have no way of knowing if the source to this plugin has been modified to do something nefarious.

Keep WordPress up to date

Just like you should keep your plugins and themes up to date, you should also make it a point to keep the version of WordPress you’re running up to date. Fortunately this is now much easier than it was in the past, with critical security updates occurring automatically. Of course, unless you explicitly disable this functionality.

Aside from new features, improvements and bug fixes, WordPress core updates also contain security fixes which may protect you from attackers exploiting your WordPress website and using it for ill-gotten gains.

WordPress Hosting

WordPress hostingWhere and how you choose to host your WordPress site will highly depend on your requirements. While there is nothing wrong with hosting and managing WordPress yourself, if you are either not as technically savvy, or you want to make sure to meet most of the WordPress security basics without doing a lot of heavy lifting, you may want to opt for a managed WordPress hosting provider such as Kinsta or WP Engine.

Since we have had websites hosted with both hosts, we have written about them. In our customer stories we highlight our experience with them. To learn more about your experience read our WP Engine and Kinsta customer story. Managed WordPress hosting abstracts away a lot of security decisions and configuration you need to otherwise worry about yourself.

Naturally, managed WordPress hosting may also not be for you. You may opt to host WordPress yourself, especially if you’re budget constrained. Self hosting WordPress also gives you greater control over your WordPress installation. To learn more about all the different WordPress hosting options and what works best for you refer to the guide to choosing WordPress hosting.

WordPress dashboard

Your site’s WordPress dashboard is a place you don’t want anyone unauthorized to be lurking. While there are some sites that have legitimate reasons to allow public users to login using the WordPress dashboard, this is a huge security risk and must be very carefully considered.

Fortunately, most WordPress websites do not have this requirement and as such should prevent access to the WordPress dashboard. There are several ways to do this and you should pick what works best for you.

A common practice is to restrict access by password protecting the WordPress Admin (wp-admin) pages. Another solution would be to only allow access to /wp-admin to a number of selected IP addresses.

Disable registration

By default, WordPress does not allow public users to register to your WordPress website. To confirm that user registration is disabled:

  1. head over to Settings > General page in your WordPress dashboard area
  2. navigate to the Membership section
  3. ensure that the checkbox next to Anyone can register is not selected.

Credentials

Like any other website, access to your WordPress dashboard is only as strong as your credentials are. Enforcing strong WordPress password security is crucial security control of any system, and WordPress is no exception.

While WordPress does not have any way to set a password policy out of the box, a plugin such as Password Policy for WordPress is an absolute essential to enforce password strength requirements across all of your users who have access to the WordPress dashboard.

Once you enforce strong password security on your website use WPScan to test for weak WordPress credentials, to make sure no account is still using weak passwords.

Two-Factor Authentication (2FA)

Two-Factor Authentication

Another essential security control for your WordPress dashboard is to require two-factor authentication. Two-factor authentication (2FA) makes it significantly harder for an attacker to gain access to your WordPress dashboard should an attacker manage to uncover a user’s password (e.g. an attacker may discover a user’s password from a data breach).

Luckily, it is very easy to setup two-factor authentication on WordPress. There are a number of high quality plugins you can use to add this functionality. Read the best two-factor authentication plugins for WordPress for a highlight of the top 2FA plugins available for WordPress.

Hardening WordPress core

Even though WordPress’s core is a secure piece of software, it doesn’t mean that we can’t harden it further. The following are a number of hardening strategies specific to the WordPress core.

Make sure debug logging is disabled

WordPress allows developers to log debug messages to a file (this being /wp-content/debug.log by default). While this is perfectly acceptable in a development environment, keep in mind that this file can also be easily accessed by an attacker if the same file and/or settings make their way to production.

WordPress debug is disabled by default. Though it is always better to double check it is — ensure you do not have the WP_DEBUG constant defined in your wp-config.php file, or explicitly set it to false.  Refer to the WordPress debug guide for a list of all the debugging options.

If for some reason you need the WordPress debug logs on your life website, log to a file outside of your web server root (e.g. /var/log/wordpress/debug.log). To change the pa

define('WP_DEBUG_LOG', '/path/outside/of/webserver/root/debug.log');

Disable XML-RPC

The WordPress’s XML-RPC specification was designed to allow communication between different systems. This means that virtually any application could interact with WordPress. The WordPress XML-RPC specification has historically been important for WordPress. It allows it to interact and integrate with other systems and software.

The good thing is that XML-RPC has been superseded by the WordPress REST API. To highlight some of the security concerns around XML-RPC; it’s interface has been the source of numerous security vulnerabilities over the years. It also can be used by attackers for username enumeration, password brute forcing. or denial of service (DoS) attacks via XML-RPC pingbacks.

Therefore unless you are actively using XML-RPC and have appropriate security controls in place, you should disable it. Since this is something easily achievable without installing a third-party plugin, we’ll cover how to do so below.

While you may simply configure your web server to block access to /xmlrpc.php, a preferred method of doing this is to explicitly disable XML-RPC using a built-in WordPress filter. Simply add the following to a plugin file and activate it on your site.

add_filter('xmlrpc_enabled', '__return_false');

Heads up

  • It’s a good idea to make use of a WordPress must use plugin for this and other similar code snippets.

Restrict the WordPress REST API

In the same vein as XML-RPC, the WordPress API is the modern way for third-party applications to communicate with WordPress. While it is safe to use, it is advisable to restrict some functions within it to prevent user enumeration and other potential vulnerabilities. Unlike XML-RPC, WordPress does not provide a simple, native way to disable the REST API entirely (it used to2, but this got deprecated, so it’s wise not to do so any longer), however, you can restrict it.

As is typical with WordPress, you may either use a plugin to achieve this, or you can add the following filter to a plugin file and activate it on your site. The following code will disable the WordPress REST API for anyone who is not logged in by returning an unauthorized HTTP status code (status code 401) using the rest_authentication_errors WordPress hook.

add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() ) {
return new WP_Error( 'rest_not_logged_in', 'You are not currently logged in.', array( 'status' => 401 ) );
}
return $result;
});

Additionally, the WordPress REST API enables JSONP by default. JSONP is an old technique for bypassing the browser’s same origin policy before modern browsers supported CORS (Cross-origin Resource Sharing). Since this could potentially be used as a step in an attack by an attacker, there is no real reason for this to be enabled. It is recommended to disable it using the rest_jsonp_enabled WordPress filter using the following PHP snippet.

add_filter('rest_enabled', '__return_false');

Refer to the filter’s documentation for more information about it.

Prevent WordPress version disclosure

Like many other web applications, by default, WordPress discloses its version in a number of places. Version disclosure isn’t exactly a security vulnerability, however this information is very useful for an attacker when planning an attack. As a result, disabling WordPress’s version disclosure features may make an attack just a little bit more difficult.

WordPress leaks a lot of version information. Luckily, this GitHub gist offers a comprehensive list of WordPress filters to disable in the form of a WordPress plugin. Of course you can incorporate this code into any existing site-specific or must-use plugins you already have.

Prevent WordPress user enumeration

WordPress is vulnerable to a number of user enumeration attacks. Such attacks allow an attacker to figure out what users exist whether a user exists or not. While this may seem harmless, bear in mind that attackers may use this information as part of a larger attack. For more information about this topic, read how to enumerate WordPress users with WPScan.

In order to prevent WordPress user enumeration, you’ll need to ensure that the following WordPress features are disabled or restricted.

  • Restrict the WordPress REST API to unauthenticated users
  • Disable WordPress XML-RPC
  • Don’t expose /wp-admin and /wp-login.php directly to the public Internet

Additionally, you will also need to configure your web server to prevent access to /?author=<number>. If you are using Nginx, you may use the following configuration to prevent WordPress user enumeration.

RewriteCond %{REQUEST_URI} ^/$
RewriteCond %{QUERY_STRING} ^/?author=([0-9]*)
RewriteRule .* - [R=403,L]

Alternatively, if you are using Apache HTTP Server, you may use the following configuration to prevent WordPress user enumeration.

if ( $query_string ~ "author=([0-9]*)" ) {
return 403;
}

Disable the WordPress file editor

One of WordPress’s most dangerous features is the ability to edit files from within the WordPress dashboard itself. There should be no legitimate reason where any user should need to do this, and certainly not to WordPress core. If anything, you want to make sure that you know exactly what files changed using a high quality file integrity monitoring (FIM) security plugin.

To be alerted of file changes use the Website File Changes Monitor plugin, which we develop.

Any file changes to your website should happen either over a secure connection (e.g. SFTP), or preferably, tracked in a version control repository and deployed using CI/CD.

To disable the plugins and themes file editor in the WordPress dashboard, simply add the following to your wp-config.php file.

define('DISALLOW_FILE_EDIT', true );

Disable theme and plugin management

A good WordPress security best practice is to disable plugin and theme management from the WordPress dashboard. Instead, make use of command line tools such as wp-cli to make these changes.

By disabling theme and plugin changes, you drastically reduce your WordPress website’s attack surface. In this case, even if an attacker successfully breaches an administrator account, they would not be able to upload a malicious plugin to escalate the attack beyond access to the WordPress dashboard.

The DISALLOW_FILE_MODS constant defined in wp-config.php disables plugin and theme updates and installation through the dashboard. It also disables all file modifications within the dashboard, thus removing the Theme Editor and Plugin Editor.

To disable the theme and plugin modifications in WordPress dashboard, add the following to your wp-config.php file.

define('DISALLOW_FILE_MODS', true );

WordPress HTTPS (SSL / TLS)

Transport Layer Security (TLS) is an absolute essential for your WordPress security, it’s free and easy to set up. Note: TLS is the protocol that replaced Secure Socket Layer, SSL. However, since the term SSL is very popular, many still refer to TLS as SSL.

When you visit your website over HTTPS (HTTP over TLS), the HTTP requests and responses cannot be intercepted and snooped-upon, or worse modified by an attacker.

While TLS has more to do with your web server, or Content Delivery Network (CDN) than your WordPress installation, one of the most important aspects of TLS (WordPress HTTPS) is enforcing it. There is a wealth of information online about how to set up WordPress HTTPS (SSL and TLS).

If you are not comfortable editing configuration files, and prefer to switch to WordPress HTTPS using a plugin, you can use Really Simple SSL or WP force SSL. They are both very good and easy to use plugins.

Next steps for an even more secure WordPress

If you have made it this far, great, but that doesn’t mean there isn’t yet more hardening to be done. The following are a number of items you can look into to harden your WordPress website even further.

  1. Harden PHP. Given PHP is a core component of any WordPress website, hardening PHP is one of the logical next steps
  2. Use reputable security plugins. Quality security plugins offer advanced security features not included in WordPress natively. There are a vast amount of WordPress security plugins out there. However, be sure to pick plugins with a good reputation and ideally ones where premium or commercial support is available
  3. Perform a file permissions audit. For WordPress websites running on Linux, incorrect file permissions may allow unauthorized users to gain access to potentially sensitive files.
  4. Perform a backup file audit. Backup files accidentally left accessible may leak sensitive information. This includes configuration containing secrets that may allow attackers to gain control over the entire WordPress installation.
  5. Harden your web server
  6. Harden MySQL
  7. Add the necessary HTTP security headers
  8. Ensure you have a working backup procedure
  9. Use a DDoS protection service
  10. Implement a Content Security Policy

Conclusion – this is just the first step of the WordPress security journey

Congratulations! If you followed all the above advice and implemented all the recommended security best practices, your WordPress website is secure. However, WordPress security is not a one-time fix – it is an ever evolving process. There is a big difference between hardening a WordPress website (one-time state) vs keeping it secure for years.

Hardening is just one of the four stages in the WordPress security process (WordPress security wheel). For a secure WordPress website all year round you have to follow the iterative WordPress security process of testing > hardening > monitoring > improving. You have to continuously test and check the security state of your WordPress website, harden the software, monitor the system and improve your setup based on what you see and learn. For example:

  • a tool such as WPScan can help you test the security posture of your WordPress website
  • a WordPress firewall can protect your WordPress website from malicious known hack attacks
  • a WordPress activity log can help you go a long way – by keeping a record of all the changes that occur on your website you can improve user accountability, know what each user is up to and also keep an eye on all the under the hood activities
  • tools such as our WordPress security & management plugins can help you ensure passwords security, harden the WordPress security process, get alerted of file changes and much more

You have all the right tools to keep your site secure. Even if you run a small WordPress website, take the time to gradually work through this guide. Ensure you don’t end-up putting work into building a great website, only to have it ransacked by a WordPress-targeted attack.

There is no such thing as a 100% effective security. However, you’re making it considerably harder for an attacker to gain a foothold and successfully attack your WordPress website by applying the various hardening techniques covered in this guide. Remember, that when attackers are targeting their next victim, you don’t have to outsmart them. You only have to be more secure than the next vulnerable website!

References used in this article

1 https://en.wikipedia.org/wiki/GNU_General_Public_License
2 https://developer.wordpress.org/reference/hooks/rest_enabled/

Leave a Reply

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

Our other plugins