WordPress Security LogoWith WordPress being deployed on 17% of the Internets websites, it is not hard to see how big of a target it can be. That is why it is so important to consider the security of your website.

I’ve compiled a long list of security tips, tricks and best-practices to help you increase your WordPress security and harden your website against intruders and malicious attacks.

Many of these tips assume at least some level of knowledge in the area of PHP and MySQL development, as well as managing a web server.  I’ve separated these into the latter half of this post, under a section called ‘Advanced Techniques’.

Also note, the information here is current as of the time of posting, and is relevant to WordPress version 3.9.1. Although some of these tips will work with other versions, there in no guarantee. Use this information at your own risk!

Keep Everything Up To Date

This is probably the most helpful WordPress security tip anyone can give; Make sure you keep WordPress up to date!

The WordPress core is not the only thing you want to keep up to date, but also every one of your plugins, and themes need to be updated regularly.  Suggestion would be to update the moment a release is available.

There is plugins that will help you monitor your core, themes, and plugins and notify you when there is updates ready. One such example is WP Updates Notifier.

Use a Strong Password

This should be a no brainer.  WordPress security hinges on your administrative passwords.  Lately there has been a rash of bot-nets launching brute-force attacks on WordPress sites in an attempt to guess passwords.  If you’re password is easy, then it’ll be easy for them to get in.

Your password should be long (longer than 10 characters), not using English words, consist of both lower and uppercase letters, numbers, and symbols. Never use personal information such as birthdates, phone numbers, addresses, names of children, names of pets, or any type of personal information that someone else may know about you.

And, it shouldn’t need to be said, but don’t use the same password for everything. Doing so leaves everything you have vulnerable if an attacker gains access to even one of your services.

Limit the Number of Login Attempts

Brute force attacks are extremely commonplace against WordPress websites, in fact, it’s probably the single biggest WordPress security risk. To reduce the likely-hood of a Brute Force attack succeeding, strong passwords, a non ‘Admin’ username and a hidden username are paramount.

Of course, that doesn’t mean they won’t eventually get in unless you stop them from making billions of guesses first. You can use a plugin such as BruteProtect to help limit the number of guesses a bot can make.

Never Use ‘Admin’ For a Username

Default installations usually use the username ‘admin’. Using this username, you are giving the would-be-hacker 50% of the information he needs to get in right off the bat. Most brute-force attacks use this username to start their attack.

Avoid using ‘root’, ‘webmaster’, or ‘administrator’ as well, as they are also commonly used.

I don’t suggest you use your real name either; this leaves you vulnerable to people who know you, or very basic social engineering.

If you are currently using ‘admin’ as a username, changing it is easy. Log in, create a new user and assign that user the ‘Administrator’ role. Now log out, and back in as that new user, and delete the old ‘admin’ user. You will be given the opportunity to assign all existing content to the new user at this time.

Your WordPress security, at least for the log in, could said to be as much as 50% more secure from this one change.

Hide Your Username

Once you’ve set a username other than ‘admin’, you need to keep it hidden. Log in to your WordPress account and edit your profile. Change the Nickname and Display Name Publicly to something other than your username.

WordPress Security - Change nickname screenshotThis way, it will be much more difficult for a would-be-attacker to compromise your WordPress security by guessing, or finding, your username.

Do Not Share Credentials

Never give out your credentials to anyone.  If they insist they need them, first make darn sure their intent is legitimate (perhaps you assigned them a task?), and consider alternatives such as granting them a user account.

Make it an office policy that if anyone is caught giving their username or password out, they should be warned, or even fired.

Limit Access To Those Who Need It

If you have only one user who needs to administer your site, then there should be only one user account in WordPress. If you have need for more than one user, than consider that WordPress has different user Roles built in.

A full list of WordPress Roles, how they relate to WordPress security, and their use is available at http://codex.wordpress.org/Roles_and_Capabilities

Use 2 Factor Authentication

For extra protection against brute force attacks, sniffing, password guessing, and other types of attacks, you can add a second means of authentication. Often this involves a third party website or a key fob that provides a unique ‘code’ which you need to enter at the time you log in. They may even be presented in the form of an SMS being sent to your phone. Your WordPress security can benefit from any extra factor you add to your log-in.

There is lots of options for 2 Factor Authentication, but our personal favorite is the Yubikey-plugin.

Avoid Free Themes

There is certainly thousands of themes out there; but they’re only as safe and secure as the person who created them was capable of making them. There is millions of amateur developers out there who don’t know the first thing about WordPress security, and there is thousands who actually create these themes with malicious intent.

If you insist on using a free theme, strongly consider hiring a professional to audit its code to ensure it is safe to use.

Use Trusted Plugins

Much the same as themes, plugins are often chalk full of security vulnerabilities. I suggest you minimize the use of free plugins where possible. If you must use a plugin, do some homework to see if others have had problems with it, and better yet, a positive experience with it. And as always, keep your plugins up to date!

Be Wary of Third Party Encrypted Plugins & Themes

Ask yourself, why does it need to be encrypted? They may use Intellectual Property protection as an excuse, but the reality is that it takes mere moments to decrypt code if you that is an individuals intent.

Encrypted code, even basic obfuscated code, can hide all sorts of problems, even with malicious intent.

Back Everything Up

No security measure is perfect. When something breaks, you need to be able to recover from it, and fast.

Back up your WordPress installation and database on a regular basis, and keep multiple instances of that backup. Consider an off-site backup if you don’t already have one set up, as a compromised site could mean a compromised backup if they are in the same location.

But, keep in mind, your WordPress security also relies on the security of your backups. The backup will contain usernames, passwords, credentials to access your MySQL database, and more. If an attacker gets hold of a copy of your backup, they’ve got everything they need to attack you from several angles.

Avoid using free cloud services and shared cloud services to store your backups. Bigger services make for bigger targets.

Keep Your Computer Secure

It also shouldn’t need to be said, but you need, at the very least, to keep the software on your workstation up-to-date, and you should have a real-time malware (virus) scanner installed.

You can further bolster your computers security with firewalls, anti-keyloggers, encryption tools, and other things. If you are in the business of creating websites professionally, your workstation should be especially secure.

You should also trust the tools you use to work with your website. Some free tools can reduce your security far below an acceptable standard, or can even contain malicious code.

Use SFTP or FTPS

When updating, altering, installing, or backing up any part of your website, use SFTP or FTPS instead of regular FTP. Regular FTP sends your password plain-text over the internet, making it vulnerable to attackers ‘sniffing the wire’. All of your content is also being transmitted plain-text, so MySQL passwords, secrets in your content or code, and everything you don’t want seen is at risk.

Secure Your Site With An SSL Certificate

For around $25 a year, and the cost of a static IP address, you can add an SSL certificate to your website, and force all logins to use it. This will encrypt all communications between your website and your browser, making it that much more difficult for a man-in-the-middle attack, or sniffing to happen.

A plugin like WordPress HTTPS will help immeasurably, as WordPress itself and many plugins do not handle HTTPS properly.

If Not Using SSL, Use Only Trusted Networks

If you’re logging in from a coffee shop, a hotel, or an airport free Wi-fi hotspot, be warned, without SSL, your password and all the data you’re entering and reading from your website is available to be picked off by anyone on the network.

Unless you’re using SSL, I strongly recommend you only manage your website from a trusted network.

Delete Unused Themes & Plugins

It stands to reason, if you’re not using it, it shouldn’t be there. You may stop using a theme because it’s not updated as often as you like; or maybe disable a plugin because you don’t need it anymore. Both present a risk, as security related bugs in the plugin or theme may still be vulnerable, even if the plugin isn’t ‘active’.

This also stands for other scripts you may install, or have installed in the past, on your website. Say you used to use Drupal, but now you’re using WordPress. If you don’t remove Drupal when you’re done with it, you’re leaving another door open for an attacker to get in.

Remove Default Content

There’s a bunch of posts, pages, plugins and the like typically installed that you don’t need. Get rid of them all, if nothing else it will keep you organized.

Be Mindful of Social Engineering

Sometimes digital security isn’t the only thing you need to be aware of. Attackers will send you e-mails that look like they are coming from your site, asking you to log in after clicking on a link… Those links might not be to your site, they could be a carefully crafted ‘phishing’ scam to get your credentials.

Occasionally you might have to deal with strange phone calls along the lines of ‘We are leaders of WordPress security technology, and we detected a problem in your site, if you give us access we can fix it for you’. Be skeptical, be vigilant.

Monitor for Malware

Malware can appear in the form of viruses, malicious scripts, robots, back-doors, trojans, and other threats to your WordPress security.

There is many monitoring services available on the internet that will notify you of malware, a common payload of online attacks, appearing on your website. Setting up Google Webmaster Tools, Bing Webmaster Tools, and even Google Alerts are free and easy ways to get an ‘early warning’ if your site is attacked without you noticing first.

Turn Off Registration for your Site

If you don’t need it, disable it. Some attacks come in the form of ‘privilege escalation’, which basically means a logged in user could gain permission to do more than the system is configured to allow. Other attackers simply use their privileges to launch XSS style attacks, phishing, or impersonate legitimate users to launch some other form of social engineering against someone who trusts your business.

Remember to Log Out

I have been to so many offices, where personnel are gone for the day, cleaning team is in, and computers are not even on screen saver, browsers open, and users are logged in to critical business applications. All the cleaning team needs to do is dust the keyboard a little too hard, and *poof* 80% of your web business is offline.

They don’t need to be physically present either; leaving your account logged in increases the odds of a man-in-the-middle attack, cookie sniffing, session hijacking, and more.

Log out when you’re done editing, it should be obvious and easy to do. Two clicks, one on the little ‘power’ button to the top-right, and then ‘Log Out’.

WordPress Security - Log Out Screenshot

And lock your computers when you leave for the day. Most operating systems can do this with an easy key combination. Windows, for example, does it by pressing the windows key with L at the same time. Takes a second, could save you hundred of hours, and your job.

Your WordPress security is only going to be as strong as your weakest link.  Don’t let that be you.

Monitor for Content Changes

One common style of attack is known as website defacement. The attacker will find an exploit and update the content of your website to reflect their particular message of choice, whether it be political, or just plain offensive. If you have relatively static pages, you can use a service such as ChangeDetection.com and keep an eye on your content.

More advanced dynamic sites can use Google Alerts to check for keywords that you wouldn’t normally have on your website.

For example, you could set up a rule with a search query as follows:

hacked site:mywebsite.com

WordPress Security - Google Alerts Screenshot

And you would be alerted whenever the word ‘hacked’ appeared in search results within ‘mywebsite.com’.

You can also use these services to monitor for unauthorized changes by people within your organization.

Don’t Advertise your Security

The more you brag about how secure you are, the more of a target you become. Also, reporting measures you have taken narrows down the attack options that a would-be-attacker has, and makes it more likely that he can launch an attack undetected, avoiding any ‘traps’ you may have set.

At the same time, take reports of security vulnerabilities seriously, and act on them quickly.

Advanced Techniques
The following techniques are a little more advanced, and may require a little bit more experience to pull off.

Don’t Develop on your Production Server

If you’re developing or testing a new theme or plugin, or any sort of alteration to your website, its a best-practice to not do so on your production servers. Untested, unfinished, or unknown code can cause all sorts of problems, including leaving glaring holes for potential attackers.

A good idea would be to run a local server, even on your own workstation, to test out new ideas before putting them into production. A good tool for Windows users is XAMPP. Be sure to try and mimic your production environment as closely as possible to avoid problems.

Some organizations will even use a three server approach: Development, Staging, and Production.

Use Secure Development Practices

If you’re developing a plugin, or a theme, it’s a good idea to follow PHP and MySQL security best-practices, as well as WordPress security best-practices.  This is going to require quite an education, so if you aren’t well versed with these best-practices, consider hiring a professional to help you out.

Limit Use of External Scripts and CSS

If you use externally hosted JavaScript and CSS, then you are inheriting some of the security challenges of the owners of that content. If they get attacked, then they could deploy that same attack on your website, leaving you at risk. Consider locally hosted solutions over third-party hosted whenever possible.

Protect the Admin Area

A smaller target is harder to hit. There is a few tips and tricks you could use, for example, to limit access to the wp-admin folder and wp-login.php.

You can limit access to wp-login.php using .htaccess which is available on most apache best webservers in a couple of ways.

Restrict Access By IP

In the .htaccess file within your WordPress root folder, you can add the following, replacing the xxx.xxx.xxx.xxx with your workstations internet IP, to limit access to the login to only your current location.

<Files wp-login.php>
order deny,allow
Deny from all
Allow from xxx.xxx.xxx.xxx
</Files>

Restrict Access To wp-admin By Password

Alternatively, or in conjunction with the above, you could lock down the wp-admin folder by forcing an additional password to be entered on access. Be warned, this can break some plugins and functionality of WordPress, so is intended only for advanced users who understand its limitations.

If your webhost is using cPanel, you can easily create the password functionality by going to cPanel -> Security -> Password Protect Directories, navigating to the appropriate wp-admin folder, and setting a username/password.

To do so manually, first, create a passwd file and place it somewhere below your web root. I recommend using htpasswd on the command line, and NOT a web based service, as they will be aware of your password. Next, create an .htaccess file in your wp-admin folder, and place the following inside; updating the path to the passwd file you just created:

AuthType Basic
AuthName "WordPress Admin"
AuthUserFile "/home/yoursite/.htpasswds/public_html/wp-admin/passwd"
require valid-user

Disable File Editing

WordPress has a handy file editor under the Appearance menu, but it’s a big risk for WordPress security. Anyone who obtains access to your WordPress installation can create and execute any code they choose on your server. You can quickly disable this, and still rely on SFTP/FTPS or SSH to edit your theme and plugins safely.

Simply add:

<?php
define('DISALLOW_FILE_EDIT', true);
//...

To your wp-config.php file.

Use Safe File Permissions

Depending on your server, different permissions are more secure than others. The thing to avoid is making everything ‘world writable’. If everything is set up correctly, ‘everyone’ shouldn’t need to write to your WordPress core installation. In many cases, files don’t need to be ‘world readable’ either. Make sure every file has the minimum permissions it needs to function, and nothing more.

Change the Database Prefix

Many script based attacks rely on the standard ‘wp_’ prefix on your tables, and changing it in your installation can help prevent these attacks.

Before attempting to change your prefix, be aware that badly written plugins and themes can break, and there is risk of data loss if not done correctly. Make sure you back up your database prior to attempting the change.

Edit your wp-config.php file and change the prefix:

//..
$table_prefix = 'wp27_';
//..

Now you need to update your MySQL tables to suit. And example of the commands needed:

RENAME TABLE wp_commentmeta TO wp27_commentmeta;
RENAME TABLE wp_comments TO wp27_comments;
RENAME TABLE wp_links TO wp27_links;
RENAME TABLE wp_options TO wp27_options;
RENAME TABLE wp_postmeta TO wp27_postmeta;
RENAME TABLE wp_posts TO wp27_posts;
RENAME TABLE wp_terms TO wp27_terms;
RENAME TABLE wp_term_relationships TO wp27_term_relationships;
RENAME TABLE wp_term_taxonomy TO wp27_term_taxonomy;
RENAME TABLE wp_usermeta TO wp27_usermeta;
RENAME TABLE wp_users TO wp27_users;

Keep in mind that the commands you need to run may differ; plugins and themes can install additional tables, and of course, WordPress changes their core from time to time.

Next you’ll need to update the wp_options table to reflect the new prefix:

UPDATE wp27_options SET option_name='wp27_user_roles' WHERE option_name='wp_user_roles';

And finally, you’ll need to update the wp_usermeta table, which can have many different tables listed. First run:

SELECT * FROM wp27_usermeta WHERE meta_key LIKE 'wp_%';

This will indicate which rows you need to manually update. Once again, just replace ‘wp_’ table names with your new ‘wp27_’.

Also note that wp_ isn’t always going to be the prefix; you will need to alter the MySQL examples to suit.

There is also scripts that will do this for you. iThemes Security is one such example.

Use a Secure Database Password

Just like all passwords, it’s important to choose a strong password for your MySQL database. Other individuals with legitimate access to the server could guess your username, and brute-force your password. And lets not forget that many hosts let MySQL be accessed from the whole world.

Hiding WordPress Version

This won’t do much, and there is a lot of debate as to how much it benefits WordPress security; but there may be ‘some’ merit to security by obfuscation. Smartest thing is to always keep WordPress up to date (meaning this would be redundant).

You can add the following to your functions.php theme file:

function wp27_remove_version() {
    return '';
}
add_filter('the_generator', 'wp27_remove_version');

Block Directory Browsing

WordPress is pretty good at always having a ‘dummy’ index.php in folders that shouldn’t be index-able; however, it is generally a good practice to disable indexing across your whole site as not all plugins, scripts and themes are equal.

Add the following to your .htaccess file:

Options -Indexes

Monitor For File Changes

Exploits will often deliver a payload that attaches itself to files that already exist on your website, or will create new ones that open ‘back doors’ for the attacker. If you keep an eye on the files on your webserver and something is added, or changed that you didn’t do yourself, it can be a good indicator that you’ve been attacked and help you investigate.

There is many plugins that will do this for you. iThemes Security is one such example.

Disallow Custom HTML

Custom HTML leaves room for XSS (Cross Site Scripting) style attacks, and most of the time, you don’t need it.

You can disable unfiltered URL by adding the following line to your wp-config.php file:

define( 'DISALLOW_UNFILTERED_HTML', true );

Update WordPress Security Keys

Changing the default WordPress security keys is a really good idea. In the wp-config.php file, you will see a sections that looks like this:

/**#@+
 * Authentication Unique Keys and Salts.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
 * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again.
 *
 * @since 2.6.0
 */

 define('AUTH_KEY', 'z%!EeA$U|ZZbI`H=r1R,C7_G)nNoS7r+/wS|Sbi3bts42f--Ju7Xdx9zy^v{3)J_');
 define('SECURE_AUTH_KEY', '`,.Tl:^8C#uV`&gt;14%Sn$b[K9Tqz@pV5;_L?4^&lt;vY3b;|(iON=*-*t|8Y1* F/s.8');
 define('LOGGED_IN_KEY', '-Z-!_fA)Q)!:*k{@l4m]%X|]Qr1?F6I0gRp&gt;![qMmLqT7!$)X0h_Jc k3Kl%mJSe');
 define('NONCE_KEY', 'Y`oRu4j.}RU-!U|DT_Ot?%WIRfBh2Fx;~]l]f!iAPDNJ|uh[6#CB;2fw Q8Yo|m[');
 define('AUTH_SALT', 'fv0K|-trCZC+;qE3+~Q&gt;Hn De-8vfHdUhE)cOb9*&lt;69mIa)wBmiD+TgAwV8&lt;z-Wj');
 define('SECURE_AUTH_SALT', 'iC3U]strtq`4X+nP2|Wd#Bk8^}-~X@t=MZoHaLz64j}IJCt9o|nD=*ZL^)9-d4L0');
 define('LOGGED_IN_SALT', 'T|x.Bk|A^bGy/cN8z^aS4HT-gS*-T56Y+it_2-J7x7 1-64Xr8|-Ib%D]&amp;+N,-#I');
 define('NONCE_SALT', '1x+zq/U|iPEtwkJ4qvOW1%-JAm[.HYUF2=iU=fbAy#bXJC5zD-,Xi+k%uNB UI67');

/**#@-*/

You can generate new random keys by visiting https://api.wordpress.org/secret-key/1.1/salt/ and copy them into your wp-config.php file.

Monitor Error Logs

Your webserver will output various kinds of logs that can detail the activity on your website. Some attack attempts leave a ‘signature’ that can be recognized in those logs. Some attacks will often have dozens of failed attempts before a successful one, and shutting the attacker down before they have a success, is a good defensive strategy.

If you have a dedicated or VPS server, OSSEC is a good monitoring tool that can help in this area.

Remove any Login Links from Themes

Again, security by obfuscation. Debatable whether it helps or not, but really, if it doesn’t need to be there, why have it?

Remove XMLRPC support

The latest versions of WordPress come with XMLRPC enabled by default, and there is no simple way to disable it.

XML-RPC can be used for pingbacks, but that can lead to DDOS style attacks from even fully legitimate WordPress sites. You can disable the pingback feature by adding the following to your functions.php:

add_filter( 'xmlrpc_methods', function( $methods ) {
    unset( $methods['pingback.ping'] );
    return $methods;
 } );

Alternatively, to avoid losing your changes when your theme updates, you can install a plugin such as this one.

Configure Cron

Many WordPress features and plugins require users to actually trigger events on the system. This can be a problem with a lower traffic website.

You can configure a cron instance to run, instead of the normal ‘trigger on page load’ type faux-cron that WordPress uses.

First, edit your wp-config.php to include the line:

define('DISABLE_WP_CRON', true);

Next, add the following to your crontab:

/15 * * * wget -q -O – http://yourdomain.com/wp-cron.php?doing_wp_cron

You may need to update the interval depending on how much work your WordPress setup needs to do, and how often. Be smart about this, setting it to run every minute may be extreme overkill that could bring down your server with too many processes overlapping.

Disable Debug Messages

Debug messages are normally disabled by default on your first install, but you may enable them for one-reason or another, such as troubleshooting a custom plugin or theme.

Make sure you always have them disabled in production, as you could present additional information to a would-be-attacker.

Make sure your wp-config.php has the following lines:

define( 'WP_DEBUG', false );
define( 'SCRIPT_DEBUG', false );

Note, as these are PHP constants, there should only be one set of them inside the wp-config.php, so make sure there is only one set referring to WP_DEBUG and SCRIPT_DEBUG, both set to false.

Moving WordPress Directories

Changing the default folders for wp-content, wp-admin and wp-includes could help prevent against a number of different automated attacks, but a manned attack it may only slow down. There is a number of risks associated with these changes, such as plugins and themes that don’t follow best-practices and hard code links to the folders, and automatic updates failing.

It can also break links to existing content, so you must back up your installation before attempting this, and approach the entire idea with caution.

You can change the default wp-content folder by first moving it to the new folder, then adding the following to the top of your wp-config.php:

define ('WP_CONTENT_FOLDERNAME', 'assets');
define ('WP_CONTENT_DIR', ABSPATH . WP_CONTENT_FOLDERNAME);
define ('WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] . '/');
define ('WP_CONTENT_URL', WP_SITEURL . WP_CONTENT_FOLDERNAME);

Change your Administrator Database ID

Quite a few scripted attacks rely on the master administrator being user id 1 in your WordPress database. Changing that value to some random number (that isn’t already used), can help against these attacks.

To do this you need to modify the database, and this is risky, so make sure you have backed up before you attempt this.

For example, you could execute the following MySQL statements on your database:

UPDATE wp_users SET ID=521 WHERE ID=1;
UPDATE wp_usermeta SET user_id=521 WHERE user_id=1;

Which would change user ID 1, to 521. Make sure you use a number that isn’t already in use.

Implement a Firewall

Your host may already have one, but if you do not, at least consider using ModSecurity and something like APF.  These will close a large number of holes for WordPress, and other services within your infrastructure.

If you are using a shared provider, you will likely not be able to implement these yourself.  Ask them what WordPress security measures are in place.  Be aware, they may be wary of providing too many details, because as far as they know, you could be a potential attacker!

Isolate your WordPress Installations

If you are sharing a server with many different websites, it’s a good idea to make sure that you are isolated from those other instances.

Of course, make sure each VHOST is set up individually, use SuEXEC or fcgi and if possible or required, use custom php.ini’s for each instance to define things like open_basedir, and limit access to the web directory of each VHOST.

Some hosts will do this for you automatically, as it’s in their best interest to protect their clientele from their other clientele.

A word of advise with cPanel installations; if you are hosting multiple accounts under one cPanel account instance, you will have a much more difficult a time securing your installations from each-other.  Best thing you can do is have a separate cPanel account for each website/instances of WordPress.

Conclusion

That’s all for now, but as you can see there is many, many things you can do to increase your WordPress security.  Keep in mind that WordPress is a constantly evolving product, and many of the tips and tricks here may become out of date.  Its important to do your research before you implement anything on your website, and of course, never forget to back up!

Also keep in mind that there is no such thing as perfect security, it’s only as good as the weakest link, and it’s a moving target.  If someone wants in, has enough time, and resources, they will eventually get in.  Be vigilant!

As I can think of more WordPress security enhancements, I will post them here, so keep this page bookmarked!

Leave a Reply