The Complete WordPress Security Guide Part 3

Ready for the big guns? Parts 1 and 2 of this security-based miniseries walked you through what needs to be done and how to do it. Part 3 is advanced information for developers and WordPress admin experts to build and maintain secure WordPress sites.

The Complete WordPress Security Guide part 3: Advanced information for web managers

Setting up and maintaining a secure WordPress site is a complex undertaking. When you're providing managed WordPress hosting services, your clients are relying on you to keep their website fully secure from hackers, malicious actors, and any security vulnerabilities.

Of course, you are welcome to review Part I and Part II of this series for all the tips in a comprehensive guide, but keep in mind that the first two installments are for a Non-Geek audience while this one is for web developers, so it's definitely solidly in the Geek category.

But you know that although WordPress core systems are highly secure, there are a lot of potential holes in plugins, themes, and updates that you need to close up, plus there's the ongoing risk that a user or WordPress admin could make changes that undermine all your hard work. Here are some of our tips for web developers, WordPress admin experts, and advanced programmers to build and maintain secure WordPress sites.

Note: This blog post is aimed at advanced WordPress developers and is written in Geek.

* This guide is aimed at WordPress websites hosted on a Linux server, but maybe relevant for a WordPress admin for sites hosted on Windows servers as well.

Disable the option to edit files from within the WordPress dashboard

By default, WordPress allows users to edit theme and plugin files through a dedicated code editor in the dashboard. In the wrong hands, this tool can be extremely dangerous and a massive security risk. An untrained but well-meaning WordPress admin could accidentally add arbitrary code to your plugin or theme, and that's why we recommend disabling this option completely.

It's far safer for a WordPress admin to edit code files only through an FTP client or a built-in file manager offered by your hosting provider.

To disable the option of editing the files through WordPress, add the following code to your website’s "wp-config.php" file. Make sure to add it above the lines /* That's all, stop editing! Happy blogging. */

define('DISALLOW_FILE_EDIT', true);

Migrate to uPress within 24 hours

Restrict access to the login/management areas

Hackers and malware try to access the wp-admin or wp-login.php areas of your website without any restrictions. If you control the firewall, we highly recommend restricting the access to these areas exclusively to the country you or your team are based in, or take it a step further and restrict it to certain IP addresses.

A WordPress admin can also protect these areas using a password on the server side that basically provides an extra layer of defense before the hacker/malware operator can access said areas. This is popular in Linux OS-based Apache servers.

Disable XML-RPC Protocol

The XML-RPC protocol is enabled by default in WordPress from version 3.5 and up to help remotely connect your WordPress website with other websites and services. Your WordPress admin might appreciate it, but it's a big security hole that can be used to attack your own or other websites.

For example, hackers or malware that try out 100 different passwords to access your account would have to make 100 separate attempts to login, giving your security systems the opportunity to recognize and block their attempts.

If XML-RPC is active, they can use the default-enabled function system.multicall to try thousands of different passwords in a far smaller number of attempts.

As a WordPress admin, you can limit the XML-RPC connection by:

  • Blocking access to the xmlrpc.php file in your firewall or in your server configuration (eg. .htaccess or nginx.conf files).
  • Installing a plugin like Disable XML-RPC, which is available for download through the official WordPress repository.

uPress Customers: there an XML-RPC toggle under the security tab which disables the protocol by default.

Apply a user protection program

By default, WordPress websites make it possible to access the user's post archive which lists all of their published posts. Bots can utilize this hole to read the user’s sensitive information by Brute Forcing their user-ID, like this:

We recommend that a WordPress admin blocks this path:*

Another issue is that WordPress version 4.7 and up includes and enables Rest API by default, as part of the core WordPress components. The Rest API allows users to easily access information from a database on a remote server (e.g. a WordPress site) using HTTP, making it easier for hackers and malware operators who are trying to steal user information.

For example, following this URL:

generates an organized JSON output of all the users on your website and their information.

It's not possible to completely disable this feature, because part of it is used by WordPress and certain plugins like the new visual editor Gutenberg. Instead, we recommend your WordPress admin blocks sensitive paths that can be utilized by Rest API.

The WordPress admin can block it by:

  • Using your firewall to block wp-json/wp/v2/users
  • Using .htaccess or nginx.conf to block wp-json/wp/v2/users
  • Using a plugin like Disable Rest API that allows you to block specific or all Rest API paths for non-logged-in users. The plugin is available for download from the official WordPress repository.

uPress customers: There’s a REST API toggle under the security tab.

Hide your WordPress version

WordPress automatically embeds a meta tag in your source code that contains information about the WordPress version you use.

<meta name="generator" content="WordPress 4.9.10">

This information is accessible to everyone, including hackers and malware. When they know which WordPress version your website is running, they can choose the best tactics to use against this specific version.

Older versions are more likely to have known security wormholes that malicious actors can exploit to enter your WordPress admin system. It's not surprising that hackers tend to look for sites with older versions of WordPress.

That's why we strongly recommend keeping WordPress up-to-date, but you should also hide your WordPress version by adding the following code to the functions.php file of your theme:

remove_action('wp_head', 'wp_generator');

Take care of XSS exploits

An XSS (Cross-Site Scripting) attack is when malicious scripts are injected into your website, usually as a script that runs alongside the browser, and are downloaded and run on visiting users' browsers.

For example, you could inject an XSS script by simply adding the script as a comment on a post, like this:


If your WordPress admin isn't prepared for XSS exploits, every user who enters the contaminated article will load the comment section and start the script running on their own browser. (A protected website will show the script in Plain Text.).

WordPress knows how to deal with XSS filled comments by default, using built-in filtering and sanitation features. XSS scripts can be injected in many other places, not just the comment section. They could be added to a search field, a contact form, etc.

The best way for a WordPress admin to protect a site from XSS exploits is by sanitizing the data before outputting the content.

Hide PHP errors

WordPress comes with an error reporting system as part of its core components. This is great for developers who want to debug coding errors in plugins or themes, but not so great for a WordPress admin who wants to secure a WordPress site, because it gives valuable information to hackers and malware operators to help them penetrate the site.

For example, a PHP error in WordPress would usually look like this:

PHP: syntax error , unexpected '^' in /wp-content/plugins/plugin.php on line 6

We recommend hiding PHP error messages by editing the wp-config.php file with the following code:

ini_set('display_errors','Off'); ini_set('error_reporting', E_ALL ); define('WordPress_DEBUG', false); define('WordPress_DEBUG_DISPLAY', false);

Reset file and folder permissions

Make sure WordPress admin permissions are set up according to official WordPress guidelines. A folder with a permission of 777 allows anyone to read and write files in the folder.

These are the recommended permissions for a WordPress website:

  • wp-config.php: permission of 600
  • All files: permission of 644 or 640
  • All folders: permission of 750 or 755

* You can adjust the permissions of files and folders through an FTP client, and by using a Reset Permissions button on some hosting services.

uPress customers: There's a reset permissions button for all files and folders to WordPress' recommendation under Development → Additional Tools for Web Hosting.

Use Authentication keys

By default, WordPress installations come with a wp-config.php file that contains empty encryption. When you install WordPress, the system should generate authentication keys, also called security keys, to encrypt and decrypt the information stored on registered users' cookies, such as user name and password.

This is how authentication keys are set by default:

define('AUTH_KEY', 'put your unique phrase here');
define('SECURE_AUTH_KEY', 'put your unique phrase here');
define('LOGGED_IN_KEY', 'put your unique phrase here');
define('NONCE_KEY', 'put your unique phrase here');
define('AUTH_SALT', 'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT', 'put your unique phrase here');
define('NONCE_SALT', 'put your unique phrase here');

And this is how authentication keys should look:

define('AUTH_KEY', 'X<@vIF23>d~#%kYe^_>xhv~xUJ*ia*y+ALlJLGv7qFJe<EnpEwD:g~~&$}+DC5eF');
define('SECURE_AUTH_KEY', 'nA@GM?#u7v99Yk+8sM|+ZeF;]P74f`2v|z]{dKS|+cojC.w<&o4LeGvv-]$FWX4^');
define('LOGGED_IN_KEY', 'UNOk*x]$V_a]]vtKZM>`gs2Ht^O/`Rl|>EJzO9/*Y|)tJ2`&rg8FZ 5`l,67)`1U');
define('NONCE_KEY', 'pc-UFE^.+7?+vPD^,i& ^^R?+|I-q+7p>?d2*NZ|zUf|?e&v&?6iz-gF+~m*?(L=');
define('AUTH_SALT', '7n_U|q1kJ)s)8_#5sb! FY]l)Y!Eyyse85!/$G>qh(XbTYpefVxC_M/naQKhM#PL');
define('SECURE_AUTH_SALT', 'Mw^0=5J5:TWi;fl|*$l|i]f7Gyw-}1@-G5ZPc1atjhg@8v#&& ?1re#D!vtE:g&^');
define('LOGGED_IN_SALT', '~hZF}x2b&F^Q-WQK8^q>5pS!|6eT^<6z!WSNcv;Jd&8mY2T9M`:S Z ;OYGd[{$e');
define('NONCE_SALT', 'rH&yz6/_S0hXVnJOJ28?]EME!}s>V<%+<[e;FEl:d)t>+P%|atn+Ktq-lpk{+WIM');

If you don't have unique authentication keys configured in your wp-config.php file, we recommend that a WordPress admin creates them at the dedicated WordPress security keys generator and configures them into your wp-config.php.

Disable PHP files in folders

Tighten up website security by disabling the option of running PHP files in folders that do not require them. For example, the folder /wp-content/uploads/ isn't supposed to contain any PHP files.

Disabling this possibility effectively blocks hackers and malware from running PHP files containing security exploits that may exist in this folder.

You can use a .htaccess file to perform this block:

# .htaccess - Disable PHP Execution <Files *.php> Order Allow,Deny Deny from all </Files>

uPress customers: This option is an integral part of our management panel and is set to block by PHP files in the uploads directory by default.

Secure vital files

The wp-config.php file probably contains the most sensitive information about your website, including access credentials for your database and authentication keys and settings. As WordPress admin, you should block direct access to the file immediately.

This can be done using the .htaccsess file:

# .htaccess - Protect wp-config.php <Files wp-config.php> Order Allow,Deny Deny from all </Files>

uPress customers: This option is an integral part of our management panel and access to this file is blocked by default.

The WordPress admin should also secure the .htaccess file, which contains your website's server configuration. If you're using an Apache server, you'd usually protect it on the server level, but if that's not possible you can use the .htaccess file to protect itself:

# .htaccess - Protect .htaccess <Files ~ "^.*\.([Hh][Tt][Aa])"> Order Allow,Deny Deny from all Satisfy all </Files>

Securing a WordPress site requires constant vigilance

When you're a WordPress admin, you can never let down your guard (and we can say the same, as managed WordPress hosting experts - we can never let our own guard down, much less that of our clients!) We've shared some useful tips that can help make it easier and faster to secure a WordPress site, whether you’re offering managed WordPress hosting services, WordPress development, or ongoing WordPress support as a WordPress admin. Disabling and blocking as many open security holes as possible and keeping WordPress security patches updated are the most crucial steps in frustrating would-be hackers and malicious actors, but we could go on and on.

As managed WordPress hosting experts, we speak your language. We can geek out with you about comprehensive WordPress security, but we can also discuss XML-RPC Protocol, Rest API paths, and XSS exploits. You can trust us with the entire gamut of WordPress questions, so the only one left is... why aren't we hosting your WordPress site yet? Click below and join us.

Explore plans

hello world!

Read more about these topics!

Related Posts

How to Install WordPress using the uPress Admin Panel

If you’re building your own website on the WordPress content management platform, you might be feeling a little nervous about how to get started. Don’t worry! We’re here with this non-scary guide that will take you through each step of building a new WordPress content management site.
Read More

How to protect your posts or pages with a password

Looking for a way to publish content on your WordPress blog that’s only visible to certain people, instead of sharing every single post with the whole world? We’ve got you covered.
Read More

Migrate WordPress Website from Previous Host

Ready to move to uPress? This user-friendly guide will teach you how to migrate your site with our Auto Migration Tool - you can complete the process and be up and running in 24 hours!
Read More