WordPress Security Hardening Guide — Checklists and best practices.

Ahmad Moaaz
10 min readApr 3, 2021

Whenever i get a client to Pentest whose site is running on WordPress, there are always these few common vulnerabilities that i come across so that is why i thought of writing a WordPress hardening guide for the devs and the Pentesters out there.

We need to know that the core system of WordPress is not always vulnerable and when it is, a new update roles out quickly and that is why we should always keep our WordPress version updated to the latest one.

Lets see some quick and simple things first that every one needs to do to enhance their security:

General

  1. Implement strong password policy not only on the admin panel but also on the FTP accounts, database, WordPress hosting account, and your custom email addresses which use your site’s domain name.
  2. Keep a regular backup of your files on a remote location, not on the hosting provider.
  3. Install minimum plugins. Only the required plugins should be installed as extra unneeded plugins will make the attack surface wider.
  4. Enable WAF — DNS level (These firewall route your website traffic through their cloud proxy servers. This allows them to only send genuine traffic to your web server) & Application level (These firewall plugins examine the traffic once it reaches your server but before loading most WordPress scripts. This method is not as efficient as the DNS level firewall in reducing the server load.)
  5. Move Your WordPress Site to SSL/HTTPS
  6. Change the Default “admin” username: The default username should always be changed because this makes brute-force attack much easier for the attacker since he/she knows the username already and needs to brute-force only the password.
  7. Disable public access to wp-json/wp/v2/users and wp-json/wp/v2/posts as these directory shows the usernames and the recent posts created which an attacker can use it to brute-force the admin page or retrieve sensitive information.

This can be done using rest_endpoints filter in your functions.php. Following filter will disable user endpoints. You can use same logic to any endpoint you want to close.

add_filter( 'rest_endpoints', function( $endpoints ){
if ( isset( $endpoints['/wp/v2/users'] ) ) {
unset( $endpoints['/wp/v2/users'] );
}
if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
}
return $endpoints;
});

If you don’t need Rest API at all and you want to disable it for some reason you can use this snippet in your functions.php.

add_filter('rest_enabled', '_return_false');
add_filter('rest_jsonp_enabled', '_return_false');

8. Show WordPress REST APIs to only registered users.

To hide the REST API to unregistered users, we must add the following code in our WordPress. Remember that you can put it in the functions.php file of your theme

<?phpadd_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;
});

Once you have put this code in your WordPress, accessing a route of the REST API on your website while not logged in will result in an error message. Your content is now protected. You can also do this with the help of Disable REST API (Not recommended, preferred doing manually) plugin.

9. Admin Panel should not be publicly accessible.

10. Disable directory listing.

11. Automatically logging out of idle users.

12. Rate-limiting should be implemented on the Admin Panel.

User should be locked-out from trying any further attempts after 3 or 5 unsuccessful one’s. For this purpose, we can use use Login LockDown plugin.

13. /xmlrpc.php should not be publicly accessible as it can bypass the restrictions on admin panel and can also perform multiple attack through it.

add_filter('xmlrpc_enabled', '__return_false');

It can also be disabled through .htaccess and can be made accessible to a specific IP

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

14. Disable file editing: WordPress comes up with built-in core editor which allows you to edit your theme and plugin files right from your WordPress admin area. In the wrong hands, this feature can be a security risk which is why it is recommended to turn off.

// Disallow file edit
define( 'DISALLOW_FILE_EDIT', true );

15. PHP File Execution in some of the WordPress Directories should be disabled such as /wp-content/uploads/

<Files *.php>
deny from all
</Files>

16. Add Two Factor Authentication

17. Change default WordPress Database Prefix: By default, WordPress uses wp_ as the prefix for all tables in your WordPress database. Using default prefix makes it easier for hackers to guess what your table name is, leading to compromise of your site/database

18. An additional security step: Password Protect WordPress Admin and Login Page for example, a basic auth.

19. A security question on the Admin login screen

20. Remove ‘Generator’ Meta tag from source code

go to the editor and open up functions.php. This is your theme functions file.Add near the top the following PHP snippet:

Add near the top the following PHP snippet:

// Custom: Remove ‘generator’ meta tag
remove_action(‘wp_head’, ‘wp_generator’);

This will remove the ‘Generator’ Meta Tag which reveals WordPress versions to attackers.

21. Remove all the *.txt files.

Some additional important checklists to enhance security

Security Implementations section wise:

Login Page

  1. Strong Password Policy
  2. Make the error message more generic
  3. Change the passwords regularly
  4. Use email address to log in instead of username
  5. Remove login links from the themes
  6. Implement 2FA
  7. Rename the URL of login page
  8. Lock-down the user after certain wrong attempts

Plugins

  1. Keep all of them up to date
  2. Install and use plugins from only reputable source
  3. Be cautious while installing a lot of plugins
  4. Delete and remove unused plugins

Administrative Panel

  1. Use WPHackedHelp scanner to search for malware
  2. Keep it up to date
  3. Password protect wp-admin
  4. No account with the username admin
  5. SSL on WordPress Admin section
  6. Install a plugin to check for any file changes
  7. Create an editor account for only editing purposes

Themes

  1. Keep them up to date
  2. Remove unused themes
  3. Remove the WordPress version from the theme
  4. Download them from a reputable source

Database

  1. Change the default prefix
  2. Weekly backup
  3. Strong password with lowercase, uppercase and numbers

Hosting Provider

  1. Prevent directory listing from .htaccess
  2. Set all the folder’s permissions to 755 and files to 644
  3. Reliable and secure hosting provider(Bluehost, Siteground)
  4. Connect to server over SSH or SFTP
  5. Make sure wp-config file is not accessible by others

It can be restricted with .htaccess

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

Until here, we talked about the security implementations that should be done on a WordPress site and what are the best practices to enhance security of your WordPress site. Now let’s see what are the common vulnerable plugins that i have usually come across in my Pentest engagements which makes the site even more vulnerable.

Security Measures to take against Plugin Vulnerabilities in WordPress

To avoid vulnerabilities in plugins, it is recommended to use only trusted plugins. Check to see how many active installations it has and when it was last updated. This is shows whether the plugins are being maintained and updated regularly or not.

Some of the common Vulnerable Plugins which people don’t update:

  1. Yoast SEO

Since 2010, there have been 10 known vulnerabilities in the plugin. Some of these vulnerabilities could potentially allow remote code execution and XSS.

The most recent vulnerability was in version 9.1 that affected users with an ‘SEO Manager’ role enabled. This vulnerability was a more complex and not-so-common issue called race condition. In this, the plugin expects a process to happen in a certain sequence, but when the sequence changes, the vulnerability appears.

2. Wordfence

In the past, the plugin has seen 10 listed vulnerabilities that have been patched. But again, in September 2018, the plugin disclosed multiple new flaws that included XSS vulnerabilities. Version 5.2.3 addressed this flaw.

3. All-in-One SEO Pack

This plugin is one of the most popular amongst all plugins and has been around since 2007. It boasts over more than 50 million downloads since its inception, with 2 million active installations.

The plugin has seen 2 known vulnerabilities that were XSS vulnerabilities as well as privilege escalation flaws.

In October 2018, a persistent XSS flaw was reported in version 3.2.6 and below. Using this vulnerability, if an attacker manages to get access to an admin account, they could execute their own codes and compromise the webserver.

Since then, the plugin has been safe. We recommend using only the latest version of this plugin.

4. Elementor

One of the most popular drag-and-drop page builders on WordPress, Elementor is wildly popular. It has over 3 million active installations and is a much-loved plugin for the ease it brings in designing web pages.

Elementor saw 2 known vulnerabilities which were privilege escalation flaws in 2017.

These flaws were discovered in the template library, page settings, and history. These flaws were fixed in version 1.8.8 and 1.8.9. Since then, Elementor hasn’t seen any security issues. However, there are at least 17.25% of users who are running on outdated versions of the plugin.

5. Contact Form 7

So far, there have been 2 known vulnerabilities in the plugin. In September 2018, the plugin disclosed a privilege escalation flaw. It allowed attackers to upload malicious files into the website’s directory. While this doesn’t cause serious damage, it opens up the door to more severe hacks.

Note: These plugins did fix these vulnerabilities and not vulnerable to these attacks anymore. Pointing these out cause most of the developers don’t bother updating the plugins leaving their sites vulnerable.

Source: https://blogvault.net/vulnerable-wordpress-plugins/

Some of the most recent WordPress vulnerabilities discovered could be found at: https://patchstack.com/database/

There are some cases where there are known vulnerabilities in the plugins but their developers did not patch it yet which make all their users vulnerable.

Example of the latest vulnerability in this plugin with no fix

Source: https://wpscan.com/plugin/123contactform-for-wordpress

Alternative CMS to WordPress in terms of security

Lets do some basic comparison between different CMS options that we have.

Drupal

  1. Has a dedicated team of security professionals (More than other CMS) and tackles the threats quickly
  2. Built-in Brute Force Detection
  3. Built-in IP Blocking
  4. IP Whitelisting
  5. Data validation: The Drupal API performs some automatic checks to help sanitize data and prevent injection attacks.
  6. Anti-DDoS: Drupal caches content to help mitigate the impact of distributed denial of service (DDoS) attacks, which attempt to overwhelm a website with malicious requests in order to shut it down.

Guardr — a free website starter kit based on the Drupal CMS

  1. Guardr follows the CIA information security triad: confidentiality, integrity and availability
  2. A default Guardr install will make your users pick passwords that won’t be in a dictionary (password_policy). It’ll keep more logs than Drupal basic (1,000,000 instead of 1,000), not only standard watchdog logs, but role changes for users, too (role_watchdog). It won’t let your browser save the password (clear_password_field). It’ll warn you when your disk is about to fill up to prevent a DoS (diskfree), hide fatal errors (hide_php_fatal_error), and remove the generator META tag (remove_generator). The Paranoia module prevents even your administrators from enabling the PHP input filter. Just in case your users create Views that list users, Username Enumeration Prevention will help prevent a list of your users being exposed to the Internet without your knowledge.
  3. Guardr goes beyond just adding some selected contrib modules by changing the default email notifications to remove references to user names and user IDs. That way any intercepted email isn’t as helpful to whoever did a MITM on your email. We even change the defaults on checking for updates to Drupal modules because Drupal should check for security updates by default. It disables displaying errors by default rather than outputting them by default because you should have to opt-in to getting debug information. Users also get blocked from creating new accounts on a Guardr site by default; administrators are the only ones who can create accounts until the administrator switches the site to public signups.
  4. If that paranoia wasn’t enough, it goes as far as to add additional documentation to settings.php to show how you can configure Drupal to connect to MySQL over SSL, though additional SSL configuration is required for generating certificates between your web and database servers.

Plone:

  1. Rare to have Common Vulnerability Exposures (CVE) published about Plone (Only 40)
  2. Supported by more than 350 solution providers in more than 100 countries

Ghost

  1. Brute force protection
  2. Data validation and serialization
  3. Encoded tokens everywhere
  4. Password hashing
  5. SQLi prevention
  6. XSS prevention
  7. Dependency management (All Ghost dependencies are continually scanned with NSP to ensure their integrity.)

Above mentioned options all seems really good and you can tell that they are security focused CMS. Why i say WordPress should be avoided because it is the most popular and widely used CMS which always makes it a target. Not saying that WordPress is a vulnerable CMS, it makes it vulnerable because of the wrong implementations of having vulnerable plugins etc and it becomes an easy target as there are plenty of resources available and a lot of exploits for it too. If we choose a CMS which is not really famous and is also focused on security, this makes it harder for the attacker to target that site because they will have to put in effort to find vulnerabilities in the core of the CMS and the plugins it supports.

Conclusion

WordPress’s core system usually is not always vulnerable but the plugins and other things makes it quite vulnerable to certain attacks. No Plugin can be 100% secured and nothing is, so one of the most important things while having your site run on WordPress is to monitor the installed plugins and to see if they have any known vulnerability publicly disclosed or not and if they released their security patch already and if they did, update it ASAP and if not, remove the plugin right away. There are some plugins which have known vulnerabilities in them and their developers did not release any security update on it leaving all its user vulnerable to attacks. These things needs to be considered when running a site on WordPress and minimum plugins should be installed which are absolutely necessary and needed.

--

--

Ahmad Moaaz

A Security Engineer/Penetration Tester who likes breaking into applications