The No Fluff WordPress Security Guide

Introduction

Before we jump into wordpress security, let's understand what security is and why it's important. 

Security definition from Google: the state of being free from danger or threat.

Now in terms of a website, what danger or threats do we face?

The answer to this question usually depends on what you plan to achieve with your website. 

Most websites act solely as a business card website that people can visit and view basic details about the business. E.g. business location, contact details, industry, products and services. 

Often these types of businesses have 5 or so web pages that contain text, images, and maybe a contact form / contact details. Generally not very complicated. However, these types of sites are usually the most likely to be attacked and compromised. Due to their simple nature, often many finer details are overlooked when setting up and deploying the site. These overlooked finer details are what attackers leverage and use to compromise the site. 

These forms of websites are highly likely to also run a content management system called Wordpress. Wordpress originally was built for only basic blogging websites, however over the years, the wordpress community has mutated it into many different shapes and sizes. 

Due to these mutations overtime, many complicated and high volume traffic websites are built on Wordpresses and its shaky foundations (both performance and security).

As a developer that is guilty of building many of these sites before, let me reassure you that there are ways to reinforce these foundations and make sure that your website is as secure as it can be.

The most common threats these sites face are: 

  1. DOS (Denial of service)
  2. Brute force attacks (login forms)
  3. XSS (Cross site scripting)
  4. Content scraping (mostly for contact details e.g. emails and phone numbers)
  5. Phishing (Contact form submissions)

The above list is not limited to Wordpress, and the following principles that are discussed in the following sections can be used on other platforms too.

Now that we understand the threats, what exactly is security when it comes to a website?

Well, web security can be seen as following the best practices to harden and limit the number of vectors our website has for attack.
 

Below is a table of contents of each topic discussed in this guide:

Section One - Keep Updated

This section discusses the urgency to keep all the dependencies of your website up to date so that known security vulnerabilities patches are deployed on your site.

Here is a non-exhaustive list of common dependencies for Wordpress:

  1. Wordpress Core
  2. Wordpress Plugins
  3. Wordpress Themes
  4. PHP
  5. Database (Mysql / Mariadb)
  6. Web server (Apache / Litespeed / Nginx)
  7. Web Hosting Manager (Cpanel, Plesk)
  8. Server Operating System (Linux / Windows Server)

The best place to get started with the above list is in the backend of your Wordpress Dashboard.

First Wordpress:

  1. Once logged in, hover over “Dashboard” on the top left of the screen, and then select “Updates”
  2. Here you should see a list for each of the below
    1. Wordpress Core
    2. Wordpress Plugins
    3. Wordpress Theme
  3. If there are any outstanding updates, a prompt will display for each of the above.
  4. Remember, take a full site backup before updating to ensure you can roll back the changes incase an update is not compatible with your site (ideally all changes should be tested either locally, or on a staging site)

The next place to check is Wordpress’s Site Tools, this is a relatively new feature in Wordpress which allows you to see a list of issues, and also server related details

  1. Once logged in, hover over “Tools” in the left hand side bar, click on “Site Health”
  2. Two tabs should appear, “Status” and “Info”
  3. “Status” displays any issues or recommendations you can make to your website for performance or security
  4. “Info” displays details about the current Wordpress hosting environment. Everything from Wordpress, PHP, Database, and hosting server versions. Each plugin may also have its own section

While in site tools, it's recommended to cross check the current versions of everything against the official version supported list. Doing so will give you an idea of if something needs to be updated or not:

  1. PHP:
    1. https://www.php.net/supported-versions.php 
      OR
      https://endoflife.date/php 
  2. Mysql
    1. https://endoflife.date/mysql 
  3. MariaDB
    1. https://mariadb.com/kb/en/mariadb-server-release-dates/ 
      OR
      https://endoflife.date/mariadb 
  4. Apache
    1. https://endoflife.date/apache 
  5. Litespeed
    1. https://www.litespeedtech.com/products/litespeed-web-server/release-log 
  6. Nginx
    1. https://endoflife.date/nginx 
  7. Cpanel / WHM
    1. https://cpanel.net/releases/ 
  8. Plesk
    1. https://www.plesk.com/lifecycle-policy/ 
  9. Ubuntu (Operating system)
    1. https://endoflife.date/ubuntu 
  10. Centos (Operating system)
    1. https://endoflife.date/centos 

Section Two - Cleaning Up

A website has many vectors of attack when it comes to security, and unfortunately always will. However, by minimising the number of vectors for attack it makes our job of securing them easier, and gives our attacker less opportunities.

The following is a list of the most common vectors of attack on our website. This list is not limited to only Wordpress sites, but any website platform that offers the same features (As most content management systems do):

  • Plugins
  • Themes
  • Users
  • Comments
  • Form Entries

By reducing the number inside each of these times, we reduce the number of vectors of attack.

Plugins

One of the main conveniences of Wordpress is the ability to add 3rd party plugins. However, plugins come in all shapes and sizes, and not all of them come up to the same standard.

By cleaning up our plugins we can remove a large number of security risks. One of the most common attack methods of a wordpress site is through the use of old and insecure plugins. By removing any plugins that we no longer require, we reduce our risk of attack:

  1. Once logged in, click on the “Plugins” tab on the left hand side bar
  2. This displays a list of plugins on our site, both inactive and active
  3. Have a look through the list and workout if there are any plugins you can deactivate and remove

Each plugin should have a link called “View details”, this gives you an overview of the plugin and who the developer is. Most importantly this shows you the last time the developer updated it. This part is important. Any plugin that hasn’t had an update in 6 months should be considered “abandoned” and should be removed (with care to ensure your site no longer requires it).

Themes

Just like plugins, themes too offer a large security risk, removing any unused themes further reduces your risk of attack. Depending on your site, you may have a custom theme, a 3rd party purchased theme, or a default wordpress theme. In theory the last two types of theme should be the most secure as they’re developers usually will provide periodic updates when required, however in reality this is not always the case.

As anyone can access the source code for these two types of themes, anyone can work out if they contain any security vulnerabilities and take advantage of this.

A custom theme usually is the best option, however they cost a lot more (5 - 10K$ in Australia compared to 50-200$ for a 3rd party theme). In saying that, custom themes often end up using similar techniques to 3rd party themes which may still open your site up to the same security vulnerabilities. Depending on the agency or developer who made your theme, it may take longer and more money to get an updated theme without the vulnerability in it.

All in all, do your research when deciding what theme to use.

  1. Once logged, click on “Appearances” on the left hand side bar
  2. You should see a list of themes, one theme should show that it is active
  3. All other themes should be review and removed if deemed appropriate (Contact your developer if you are unsure)

Users

When it comes to any system that is accessible to the public, user logins are probably the greatest security risk. It's common knowledge that humans are notoriously bad at generating secure unique passwords. It's for this fact that so many people have insecure passwords that they use across multiple platforms. As we know data breaches are all too common, and many platforms still store passwords as plain text. This means that there's possibly many Wordpress accounts out there that use the same logins as ones exposed in one of the many data breaches.

Cleaning up user accounts is important, as it reduces the number of logins an attacker can use to gain access to our site.

  1. Once logged in, click on the “Users” tab on the left hand side bar
  2. This should present to you a list of all the users on your site
  3. If you have an “Ecommerce” site or “Forum” site, it may be easier to narrow down the user accounts to the following groups:
    1. Administrator
    2. Editor
    3. Author
    4. Shop Manager
  4. These roles are the ones with the most power, removing any unused users from these categories will reduce the number of chances an attacker can gain access to the admin side of your website

TIP: For any user accounts you are unsure of, run their email address through the following website. This website shows if the email address has been compromised on other websites / platforms due to data breaches. If they have, be sure to update their password if possible:
https://haveibeenpwned.com/


Comments

Comments these days aren’t too common on most websites due to the “Web 2.0” (facebook and twitter) movement. However many older blogs still exist with comment sections. Depending on your site, it’s a good idea to prevent users from commenting on it, as it allows your site to be used to target your viewers in phishing attacks.

E.g. An attacker posts a comment on one of your blogs, in the comment is a link. This link could take them to a fake website that requests contact details, or payment information. Any user that goes to your site can see this comment and might be enticed to click on the link, if they do click on the link, it's possible they then fall victim to the attacker (payment scams, identity fraud etc.) This is only one of the many different ways an attacker can use comment links to prey on your users.

For the safety of your visitors, it's good to ensure the comments on your site don’t contain any phishing scams (it is also good for SEO as well)

  1. Once logged in, click on “Comments” on the left hand side bar
  2. Review all comments and remove any that look like spam or phishing scams
  3. A common review method is to look for links, or text that isn’t english, or uses many emojis / special characters
  4. Once you have finished reviewing any comments, and removed any suspicious ones, take a look at your current comment settings
  5. Hover over the “Settings” tab on the left hand side bar, and click on “Discussion”
  6. You should be presented with a list of settings that all relate to the comments section
  7. Ideally no one should be allowed to post a comment without it being reviewed by an admin first


Form Entries

Similar to comments, form entries are a common place for phishing scams to live. While form entries aren’t available to the public, anyone with an admin login can still view them. For this fact, it's best to remove any suspicious ones just in case.

Now as there are many form plugins out there that store entries in many different ways, I can only suggest accessing the settings section of the plugin in order to view the entries. Generally there is an option to view entries from there.

Failing that, googling/youtubing how to view entries for your form plugin is probably the next best step.

Section Three - Hardening

While the other two sections were kept fairly high level, this section dives into the weeds of security hardening a website from the backend. This involves installing a couple of plugins, editing config files, and making code changes. If possible consult with your developer or IT support. As always, make sure to create a backup before making any changes.

As this section is quite lengthy, here is an index for each of the topics discussed:

Rewriting login route

For anyone who has ever studied the traffic log files of a wordpress website, they might’ve noticed that there's always a consistent flow of failed login attempts on the default wordpress login route (e.g. https://<yoursite.com>/wp-login.php). This is because Wordpress is a well known CMS, and because of this, many bots are set up to attack these login routes. By rewriting the default login route, we can mitigate brute force login risk on our site.

Now, generally I’m not a fan of plugins, let alone security plugins. However, if there was one plugin that I had to install, it would be this one. It's very light weight, but the benefits it brings is enormous. Ideally this should be a feature within Wordpress Core.

  1. Download the free plugin “WPS Hide Login”
    1. https://wordpress.org/plugins/wps-hide-login/ 
  2. Install on your site
  3. Configure the login route in the wordpress “Settings” section under “General”
  4. Ideally you name this something other than “/login” (the default)
  5. NOTE: make sure to note down the new login route, as incase you forget it, you will need to remove the plugin from the plugins folder via your hosting provider to be able to login again

Security Plugins

As mentioned, I'm not a huge fan of plugins, let alone security plugins. However there is some value to be had if you pick the right one.

I think the main issue with security plugins is that webmasters chose the first plugin that mentions security without actually looking into what it does.

In this stage of the hardening process, our main concern is the following:

  1. 2FA (Two Factor Authentication)
  2. Password Requirements
  3. Refuse Compromised Passwords (cross reference with haveibeenpwd)

Any feature outside of the above list is generally useless. Many security plugins try to handle tasks that shouldn’t be run at the CMS level, such as the following:

  1. Firewalls
  2. Logging

These two functions should be handled on the server level which is optimised to handle these functions. Enabling these functions on the CMS level takes away too many resources from normal traffic (e.g. your customers trying to purchase products).

The following plugin I recommend as you can pick and choose the functions that you require.

  1. Download the free plugin “Ithemes Security”
    1. https://wordpress.org/plugins/better-wp-security/
  2. Configure settings for the following functions:
    1. 2FA (Two Factor Authentication)
    2. Password Requirements
    3. Refuse Compromised Passwords (cross reference with haveibeenpwd)
  3. Once set up, access the “Ithemes Settings”
  4. Click “Configure”, scroll down to the “Logging” section
  5. This section adds data to the database which can impact performance and increase the size of the database (depending on the volume of traffic)
  6. Reduce the retention level to below 30 days, and further if you notice a significant increase in database size (large database size reduces the site performance and increases query times)

SSL

It’s increasingly uncommon these days to find a website without SSL, however many old sites still don’t have SSL configured, or configured correctly. As this is a hosting issue. Contact your developer or IT support to check that SSL is set up correctly.

SSL is important as it encrypts the traffic between the visitor’s browser and your website. If it wasn’t for SSL anyone listening on the network would be able to see confidential information being communicated (e.g. password, bank details, forms of identification).

SSL prevents these attacks known as “Man in the middle” attacks.

HTTP Headers

HTTP headers are what the server sends to the client (visitor) to lay down the rules of communication. These rules are important as they can prevent many common attacks on the client side.

The most common headers to use are:

  1. HSTS
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security 
  2. X-XSS-PROTECTION
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection 
  3. PREVENT CONTENT SNIFFING
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options 
  4. PREVENT CLICKJACKING FROM EXTERNAL ORIGINS
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options 
  5. SECURE COOKIES
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#security 
  6. SAME SITE COOKIES
    1. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite 
  7. MORE
    1. https://infosec.mozilla.org/guidelines/web_security 

HTACCESS Rules

Below are some Apache rules that filter the url requests to make them more secure and prevent common attacks. These rules are fairly common, and can be found for other web servers such as Nginx.

.htaccess security rules (Apache):

  1. PROTECT AGAINST SQL INJECTIONS
    1. https://stackoverflow.com/questions/29887663/stop-sql-injection-through-htaccess 
  2. DISABLE DIRECTORY BROWSING / INDEX
    1. Options All -Indexes
  3. DENY WORDPRESS MISC FILES / FOLDERS (WORDPRESS)
    1. https://wordpress.org/support/article/hardening-wordpress/#securing-wp-includes 
    2. https://wordpress.org/support/article/hardening-wordpress/#securing-wp-config-php 

Cloudflare

If possible, create a free account through cloudflare, and host your DNS through them. Cloudflare provides features such as DNS, CDN caching, and proxy mode (to name a few of the free features). From a security point of view, the proxy mode in cloudflare hides the IP address of your hosting server which provides one more layer of security. If the attacker can’t see where your website is hosted, it makes it even harder for them to attack it.

File Permissions

Wordpress.org also has a guide on basic hardening. The following link discusses the correct file permissions to secure a wordpress instance.

Insecure Wordpress API Routes

In Wordpress 4.7, the WP-JSON API was released. This api is used to help run wordpress as a headless CMS, and also is used in the new Gutenberg block editor.

However, one of the routes that was created when this API was released, was the users route. This route generally doesn’t get used, however it enables non-authenticated users to view a list of existing users and their usernames.

This means that anyone with a bot can quickly find a list of usernames and start using them in their brute force login attempts.

By adding this to the end of any wordpress domain, you will see a JSON object of all the registered authors on the site:

  • https://<example.com>/wp-json/wp/v2/users

Basic authentication requires two pieces of data, one username, and one password. Having two pieces of data needed to authenticate a user makes it twice as hard for an attacker to guess the correct credentials. Due to the api route, attackers now only have to guess the password to the website, making attacking the authentication process of your site easier.

How to disable the WP-JSON authors route:

Forms & Recaptcha

One of the most common features on a Wordpress website are contact forms. These forms come in many different shapes and sizes, however they all primarily do the same thing.

Most forms will have the following fields:

  • Full Name
  • Email Address
  • Phone Number
  • Message

The above list of fields if not handled correctly can open your site up to attackers.

Here is a list of ways to protect these fields (using gravity forms as an example, but can be used on any form plugin)

  1. Set a limit for characters
    1. E.g. 50 for full name, and 300 for message
  2. Set required fields
    1. E.g. Full name, email, and Message
  3. Add recaptcha to the form
    1. https://www.gravityforms.com/blog/add-recaptcha-to-your-forms/
  4. Add custom spam filtering (validation) to the form (check for keywords, non-english characters, and html/js)
    1. https://docs.gravityforms.com/gform_field_validation/

Applying the above rules to any form will ensure that your spam will be kept to a minimum (at least automated spam), and reduce the likelihood of a phishing attack.

Hide Wordpress Generator Version

One of the greatest rules of security is making it as hard as possible for an attacker to work out what system it is they are attacking. Most attackers are lazy and only use well known exploits to attack websites. However, if they don’t know what platform you are using, it's harder for them to find the right exploit to use.

Wordpress Config (disable file changes, theme editor, debugging)

If an attacker ever does get access to the backend of your Wordpress site, It's possible to add rules to ensure that they have as limited access as possible.

Disabling the theme editor in the wordpress dashboard is a great way to prevent attackers editing the core files of your website, without having access to the hosting account (e.g. Cpanel/ Plesk)

  1. In your wp-config.php file add:
    1. define( 'DISALLOW_FILE_EDIT', true );

You can also disable the adding of new plugins and themes by adding the following line:

  1. In your wp-config.php file add:
    1. define( 'DISALLOW_FILE_MODS', true );

While it can be risky to allow wordpress to auto update due to breaking changes from major releases, it’s a good idea to only allow Wordpress to auto update to apply security fixes, this can be done using the following line:

  1. In your wp-config.php file add:
    1. define( 'WP_AUTO_UPDATE_CORE', ‘minor’);
  2. To read more:
    1. https://wordpress.org/support/article/configuring-automatic-background-updates/

Another common line to add to the wp-config file is to disable debugging. Debugging statements can be used by attackers to further develop techniques to expose vulnerabilities and discover points of attack. Debugging mode should only be used by developers in staging/development as it exposes sensitive information about the underlying technologies used.

Ensure the following line is set to false:

  1. In your wp-config.php file:
    1. define( 'WP_DEBUG', false );
  2. To read more:
    1. https://wordpress.org/support/article/debugging-in-wordpress/

Section Four - Monitoring

The likelihood of a successful website attack is similar to that of falling off a bike, it’s not a matter of “IF”, but a matter of “WHEN”.

If an attacker makes it their life goal to get into a website, they will find anyway possible to get it. All we can do is put measures in place to make it as hard as possible for them, and give them as little useful information once they get in. This is what we did in our hardening process.

Now it’s time to sit back and wait for that moment they do get in. The best way to do that is to set up monitoring to detect when an attack is occuring.

Below are some tools that i recommend you setup:

  1. Uptime robot
    1. https://uptimerobot.com/ 
  2. Netdata
    1. https://www.netdata.cloud/ 
  3. Abuse IP DB
    1. https://www.abuseipdb.com/ 

The above tools first allow us to workout if our site has been taken offline (uptime robot), the next alerts us to any system level warnings such as a spike in network traffic and or CPU/MEMORY/DISK usage (netdata), and finally if our comprised site/server has been reported by other sites as malicious (abuse IP DB).

Depending on the hosting provider you are with, you may also be able to install anti-virus systems such as the following:

  1. Imunify360
    1. https://www.imunify360.com/ 

If your website ever does become compromised from an attack, it's very common for the attacker to publish content on your website. Often this is done for SEO reasons to increase the perception of spam websites through backlinks (an old school SEO trick). Once you believe you have recovered your site, run a site crawler over it and check for any external links:


Note: Depending on the size of your site, you may be limited in crawling the whole site as the free version limits you to 500 URLs. For smaller sites, this shouldn’t be an issue.

Section Five - Backups

Now when the day comes that your site has become compromised, you will want to recover from it as fast as possible. The only way to do that is to have backups in place that you can restore from.

Now depending on the nature of your site, your backup retention may different. For example, simple sites might only retain 1 main backup and 7 days of incremental backups on a weekly rotation.

Other sites, such as ecommerce, may need to retain backups longer due to financial reporting requirements (e.g. 26 months).

As every site’s hosting system is different, the following rules are only a general guide to creating backups:

  1. Backups should be created during low traffic periods. If this is not possible, consider having a replication database setup only for the purpose of generating backups.
  2. All backups should be automatic, this ensures that there is no human error, and a consistent flow of backups are made
  3. All backups should be stored on an external server. This ensures that if your site or server is compromised, then you can still rely on the availability and integrity of your backups
  4. Backups should be generated external to your web application. Don’t use backup plugins as they are usually inefficient, and often lock you into their proprietary restore methods (e.g. you can only restore if you use their plugin etc)

Conclusion

In summary web security is a constant battle, and one that can never be truly won. The best we can do is constantly take the required precautions and put in measures to reduce the impact of a security attack.

The above information is not an exhaustive guide, and I encourage you to do your own research on the topic.

If there are any additions or questions you may have, feel free to reach out to me.

If you would like a security audit of your current website, please get in contact with me on the below form.

Have a nice day

Website Audit Enquiry Form