Securing WordPress Against Hackers and DDoS Attacks

By Robert Gibb

There’s no disputing the popularity of WordPress, which powers more than 74.6m sites around the world, with 48% of Technorati’s top 100 blogs being managed by the platform. In the online world though, anything that’s popular is more open to attack and WordPress is no exception. However, the types of attack that tend to hit WordPress sites – unless you’re a big brand – are generally carried out by people without a huge amount of technical know-how. These are often referred to ‘script kiddies’ as they use common code, techniques and kits in order to hack target sites.

XML-RPC for WordPress

The good news about this is that it means that often an attack can be dealt with quickly and easily. It’s not necessary to get to the stage where an attack does damage though, as most can be prevented in the first place. So today, we’ll be looking at how you can secure your installation and avoid common hacks.

Start with the Server

Before you think about securing your site, you should start from the ground up and that means making sure that your hosting server is secure in the first place. Starting with the basics, you should choose a host based on security and reputation and not on price. Whilst I’m sure there are some decent cheap hosts out there, for the most part hosting that costs you $2 per month is not going to cut the mustard.

Most of the managed WordPress hosting services have a reputation for secure hosting. They don’t all allow some performance-related plugins though, so you should check first to see exactly what access and level of control you have.

Most of them offer:

  • Managed WordPress hosting
  • Automatic security updates
  • Daily backups
  • One-click restore points
  • Automatic caching
  • Top-tier security

Whatever host you decide to go with you should check that they offer the following:

  • Run stable versions of server software and patch as necessary
  • Enable a server-level firewall
  • Allow you to back up and restore often and easily (site and database)
  • Intrusion detection

Managed hosts (such as WPEngine for example) use caching which is passed through a CDN, so if you really don’t want to use a managed WordPress host, then do consider implementing a CDN alongside a caching plugin such as W3 Total Cache. This is a simple way of setting up your site so that all traffic that’s passed through the CDN caches is then also passing through a secure socket layer (SSL/TLS). If you need a hand getting your head around these technologies, I’d recommend the following visual guides by MaxCDN. In the interest of full disclosure, I work for MaxCDN, but I’m sure you’ll find them to be useful resources:

Unfortunately, WordPress installations on shared servers, rather than those on a VPS or dedicated server, are generally installed and configured in such a way that’s easiest for the host, but not necessarily the most secure.

Note that the following configurations are for advanced users who are familiar with coding or basic sysadmin tasks. If you’re not, then ask your web developer to set this up for you.

Logins, Passwords and Plugins

Just a quick word on this one that bears repeating given that more than 70% of WordPress installations are vulnerable to attack. Always ensure that when you have installed WordPress that you update to the latest version as soon as it becomes available. The same goes for your theme and for all plugins that you use. The same applies to your server software. It might sound obvious to many of you, but the statistics speak for themselves, there are many, many older versions of the platform installed.

When it comes to passwords, I come across people on a daily basis who still use something like ‘companyname123’ as their password and these are people that are in the tech industry and should know better. So for yourself and every other user, generate complex passwords and store in a password manager such as LastPass, it’s safer that way.

Apply Automatic Updates

To ensure that minor and major updates take place in WordPress automatically, you can make a small change to the code which will apply them. This removes the need for you to do it manually (only minor updates are applied automatically to WordPress v.3.7 and later) but you should ensure that you enable automatic, frequent backups in the event that something goes wrong and it takes your site out.

To enable updates, apply the following code to your wp-config.php file:

#Enable all core updates, including minor and major:
define ( 'WP_AUTO_UPDATE_CORE', true );

It’s more common that you’ll experience a problem with automatic updates if you use plugins that are not updated reasonably frequently, so do try to ensure that the plugins you install are maintained and support is available where possible.

Disable PHP Error Reporting

If a plugin or theme that you’re using throws up an error, then it’s possible that the resulting error message will display your server path which in turn could be intercepted by hackers. With this in mind, you should disable error reporting by adding the following code to your wp-config.php file:

error_reporting (0);
@ini_set ('display_errors', 0);

Alternatively, if you’re not confident when it comes to editing your config files, then you can ask your web host to disable it for you.

Stop Brute Force Attacks

If you were to monitor how many login attempts there are on your WordPress site each day you’d probably be shocked. These are common attacks which are preventable to some degree by using complex passwords. Brute force attacks generally come from a botnet that attempts to guess your admin password. You can mitigate the risk and stop most brute force attacks by adding an extra layer of protection at the login screen level with HTTP AUTH.

To do this you’ll first need to password protect your directory by setting up .htaccess password protection. Once you’ve done this, you need to add the following code to your .htaccess file:

#Protect wp-login
<files wp-login.php="">
AuthUserFile ~/.htpasswd
AuthName "Private access"
AuthType Basic
require user mysecretuser
</files>

This will bring up the authentication box which prompts you to put in your username and password and you’ll then be required to login on the normal WordPress login screen – you should of course use different passwords for both.

You can also prevent brute force attacks by monitoring IP addresses that attempt to login and then locking them out. Or, you can simply change the admin username from ‘admin’ to your own name or something else and then delete the default admin user profile. You and your webmaster/developer really should be the only people with administrative rights across the site.

URL Based Exploits

These are really a stab in the dark for hackers who attempt to find weak spots in the site by making URL requests that should return an error but are sometimes completed.

The URL might look something like this: http://yourwebsite.com/your/files/%3G/config

Commonly, a hacker will use an opening bracket in the URL so firstly, to overcome this, it’s necessary to generate a 403 Forbidden page to stop any request that contains the bracket. To do this, just paste the following line into your .htaccess file:

RedirectMatch 403 [

To create a more complex ruleset, you needn’t write all the code yourself. If you’re familiar with working with .htaccess and your site is on an Apache server, then you can use the 5G Firewall which is a blacklist for common exploits. You don’t have to use all of the lines either, as it’s modular, and in the event that it does produce errors, you can delete line-by-line until you discover the problem.

You can protect the .htaccess file itself by adding the following line to the file:

<files .htaccess>
order allow,deny
deny from all
</files>

WordPress Security Plugins

You can of course use one of the security plugins that are available for WordPress too. Before installation, you should check that any plugin you use is supported and updated frequently. If so, then you should also check out the ratings and reviews to determine which is seen to be the best by the WordPress community.

Remember too, that if you have a lot of plugins on your installation, to periodically removing anything you’re not using. Ask yourself if the functionality that any given plugin allows you is really necessary and cut out the ones you can do without. For those plugins that you’ve deactivated you should also delete them as they provide a potential way in for a hacker. If plugins are no longer supported, then you should look for an alternative as it’s bound to create a vulnerability at some point, if it hasn’t already.

For the most part, WordPress security is about using common sense and understanding that a lot of the time, hacks and malware can be put down to errors by the end user. For the most part, hackers get in via exploits in software, so if you ensure that you always have the latest versions you’ll do a good job protecting yourself. Hackers look for the easiest route unless they are targeting you specifically, so tighten up your site and don’t make it easy for them.

Further Reading

If you’re interesting in reading more, here’s a selection of previous articles related to WordPress security on SitePoint that are worth taking a look at:

Comments
ProfesorJorge

Hi There:

Applying a automatic update in wordpress is evil. Let's say that i build a site for a customer with a specific plugin (usually we used more than 5 plugins). The next time that Wordpress will update, it could breaks the functionality of some (all) plugins. This without counting the template of the site.

Mittineague

Well, it does have the
Important! Back-up your database and files before proceeding Warning,
but we all know how effective that is wink

Of course an auto "rollback" (or at least a button) to correspond with the upgrade upon any FAIL would be ideal.

gibbiv

Hey @ProfesorJorge. Thanks for the response! In the nature of this post (high security), I disagree that it's evil. However, in terms of making sure functionality doesn't break (especially when using multiple third party plugins that you don't control), applying an automatic update is evil.

Everything requires balance though, and every person's case is different. There may are some scenarios where applying an automatic update is an effective - even enforced - security measure.

picwellwisher12pk

You can also put your wp-config.php file one step above its root directory. It will be accessible to WordPress itself but not to others unless WordPress is installed in some sub-directory.

picwellwisher12pk

Avoid using wp_ prefix for WordPress Tables, and avoid using Admin username just like told in this article.
There is a plugin "All In One WP Security & Firewall". It can do many of these things for you. But be cautious about using it. If you know things well you can extra-tight your security with this plugin.

smitka

I just tranlated slides from my WordCamp speech to English (it is the first version of translation, there may be many grammar mistakes). You can find many security tips there.

@picwellwisher12pk I don't like to move wp-config up. This action prevents reveal information when server stops to interpret PHP code and shows source code. There was a bug in Plesk years ago that allows to show source code - this is the origin of this technique. If you move wp-config up, you need to allow scripts to access directories outside web. It may pose a greater risk.

Changing wp_ prefix is good advice, but it prevents only against simple bots and script kiddies. If SQL injection is possible, you can get correct prefix easily. Good practice is to block queries including "union" and other suspicious SQL commands.

gibbiv

Awesome advice @smitka. And thanks for translating your presentation and sharing it here. There's a lot of good WP security advice in it. I really love slide 13 and 15 and how you point out the misorder of priorities in relation to business impacts.

php

@smitka What WordPress security plugin do you recommend?

php

Hello! How do you password protect your directory by setting up .htaccess password protection?

smitka

Hi, the tutorial on wpbeginner looks very good. Pay atention to the "Admin Ajax Issue" section to allow admin-ajax.php. Some plugins also use admin-post.php file.

smitka

There are three very good plugins:
WordFence
iThemes Security
All in one WP security and firewall

My favourite one is WordFence. It has some interesting features:

  • Limiting (not blocking) some traffic
  • Notification when plugins/themes update available
  • File change detection with possibility to roll back changes

On the other hand iThemes provides pretty good url filtering and has ability to change wp-admin slug.

I really like combo of WordFence + some rules from .htaccess generated form iThemes Security + rules to block queries contain "wp-config.php" and to block harvesting user names.

I usually don't use security plugins on my own servers - I block login and scanning attempts with fail2ban and use WAF (naxsi) to enhance overall security (but it is quite hard to maintain rules).

php

This is great. Thanks so much!

I have one more question. How do you change the default WP login.php to something else?

smitka

If you use the "hide backend" feature in iThemes Security, login.php is also hidden (until you visit new wp-admin URL).

mginop

Be careful copying and pasting the code shown in the article above. They contain smart quotes, not regular straight quotes.

gibbiv

Thanks for pointing that out, @mginop!

AmitMojumder

Great Post. But I think you could have added few more aspects of security smile

chrisburgess

Hi @AmitMojumder -- security is a very broad topic. If there's ever anything in particular you'd like to see on the WordPress channel, let me know and I'll feed it back to the authors smile

@mginop thanks for the heads up, I've fixed the smart quotes!

smitka

Hi, I discovered interesting security plugin - https://wordpress.org/plugins/wp-simple-firewall/, it looks promissing.

Features:

  • simple interdaces
  • audit log - almost all actions are logged - login, plugin install, mail sent, new content
  • selectable autoupdater
  • 2 factor authentification with Yubi keys (FIDO is not supported)
  • common exploits filter (rev slider...)

Downsides:

  • no 404 detection
  • no file changes detection
  • block php uploads only in WP uploader (via hook, no via .htaccess)
dewalds86

The best way to secure your Wordpress website is not by using a plugin but by denying access to certain directories through htaccess file and your robots.txt file. Also choose a secure hosting provider.

kbez

I added the bit about the htpasswd to my htaccess, but now scheduled posts don't publish automatically anymore. I really need the password as the site is under constant attack. Any suggestions?

gibbiv

Hey @kbez. Your wp-cron.php file is probably being interferred with.

Following this http://www.summet.com/blog/2012/04/26/missed-schedule-for-wordpress-posts-due-to-htaccess-password-protection-blocking-wp-cron-php/ and/or this https://wordpress.org/support/topic/wp-cron-with-htaccess-cron-jobs-not-running should do the trick.

Please let me know if you still have problems after following these guidelines.

kbez

Thank you for the help @gibbiv! My .htaccess already has the following instructions and still missed the schedule:

<Files wp-cron.php>
Allow from all
Satisfy any
</Files>

Scheduled posts stopped working when I added:

AuthUserFile /path/to/.htpasswd
AuthName "Login first"
AuthType Basic
<Files "wp-login.php">
Require valid-user
</Files>

Does the order of the text in the .htaccess matter? I followed a few howto's like the one you wrote and added instructions to protect wp-config.php, install.php, readme.html, php_error.log, as well as the following:

# Block URL based exploits
RedirectMatch 403 \[

# Ban double slashes in all URLs
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /(([^/\ ]+/)*)/+([^\ ]*)
RewriteRule ^ /%1%3 [L,R=301]

The above was added to the bottom of the .htaccess after the caching settings added by W3TC. In my wp-config.php I activated PHP error logging by adding:

@ini_set( 'log_errors', 'On' );
@ini_set( 'error_log', '/path/to/php_error.log' );
@ini_set( 'display_errors', 'Off' );
define( 'WP_DEBUG', false );
define( 'WP_DEBUG_LOG', false );
define( 'WP_DEBUG_DISPLAY', false );

This error log says nothing about wp_cron though.

I'm also in contact with my host and will give feedback if they have any success. Thanks for a great forum.

gibbiv

Hey @kbez. Definitely let us know if your hosting provider offers you a solution.

Recommended
Sponsors
Get the latest in WordPress, once a week, for free.