With the rise in data breaches, malicious attacks and website defacement, it is vital you begin exercising top-notch security! Treat your website like Fort Knox and fortify your defenses. Although this article is directed towards a WordPress website or a Multi-Site Network, many of the aspects we cover can work for your stack - you can reference this article and customize your way to security.

We shall begin with beginner-level type security tweaks and increase with complexity. Only attempt what you're comfortable with. If you need assistance with the complex aspects, we provide professional WordPress consulting services and general security services.

If you're looking to cleanup your website after an attack, head to our Hacked Website Cleanup article.

Beginner Level Security

Security Through Obscurity

The first step to securing your WordPress website is to not simplify things for your attackers. Majority of WordPress websites are breached due to users using common usernames & passwords for administrative accounts. It is highly common for hackers to try common administrative usernames such as:

  • admin
  • administrator
  • webmaster
  • {yourdomain}

Using common account names such as above along with brute force and dictionary tools, they can launch an attack on your website and easily penetrate your lack of defense.

Suggestion: We strongly advise an odd & unrelated username for your administration account. Something you will easily remember but your enemies will never guess. For example, if you're a moving company in Tampa, have your WP administrative username be: [email protected] All you have to remember is your first name and three random words. Make sure they're random too, so you don't fall victim to social engineering attacks.


Password Complexity

Locking down your username with the instructions above will improve your security tenfold. We also have to suggest that you not use weak passwords but we also suggest not using something crazy ridiculous. Refer to the XKCD Comic below:

As illustrated a password like "peanut duck lightbulb thunder" is far easier for you to remember and more secure than "[email protected]!!faf8fa." Practice best practice!


Platform & Plugin Updates

It is extremely important to keep your WP core platform as well as your plugins up-to-date. Many malicious attacks happen through extremely popular plugins. Majority of the time WP will warn you if you are running an old version of anything.

When a vulnerability is discovered it will be made public so that WP core & plugin developers can actively secure their code. Most authors tend to release a patch or update within a few hours of the vulnerability release. This is adequate time for you to update your website before you suffer from a hack.

Not only will keeping everything up-to-date protect you, you'll also receive the latest and greatest in a plethora of new features!


Clean Access Points

Your servers are only as secure as your access points. If your computer is infected with malware, spyware, trojans, viruses and the like; you’re at risk. It is possible for hackers to swoop up your login credentials before you even pass them onto your web server. We recommend running Anti-Virus and Firewall software on your machine to prevent infection. Clean access points aren’t limited to your local machine either.

Unsecured WiFi networks are vulnerable as well. In dirty WiFi zones you’re highly susceptible to Man-In-The-Middle (MITM) Attacks. This is when you think you’re communicating directly with your web server when your traffic is actually being altered & monitored by the man in the middle. One of the best methods to prevent this attack is to encrypt your connection with an SSL certificate. This will also add SEO value to your website!

Beware: Make sure you’re connecting to a legitimate WiFi source. MITM Attacks are common in coffee shops, airports & hotels. The hacker will setup a WiFi hotspot on their laptop and use inconspicuous network names. You will blindly connect to it and they will intercept and route all of your traffic!


Easily Lockdown WP

The power of WordPress is in its plugins and we strongly recommend the security plugin, Wordfence. Both free & premium versions employ powerful lines of defense for your WP installation. And with WP you can simply One-Click-Install.

What Wordfence settings do we recommend?

  • Scan files outside your WordPress installation
    • Wordfence -> Options -> Scans To Include
  • Scan theme files against repository versions for changes
    • Wordfence -> Options -> Scans To Include
  • Scan plugin files against repository versions for changes
    • Wordfence -> Options -> Scans To Include
  • Immediately lock out invalid usernames
    • Wordfence -> Options -> Login Security Options
  • Lock out after how many login failures: 5
    • Wordfence -> Options -> Login Security Options
  • Lock out after how many forgot password attempts: 5
    • Wordfence -> Options -> Login Security Options
  • Disable Code Execution for Uploads directory
    • Wordfence -> Options -> Other Options

Each WP installation will be different, so play around with all of the settings Wordfence has to offer until you get it how you need to be!


WordPress Security Keys

If you haven't already done so, it is highly recommended that you install security keys for your WP installation. The keys will improve encryption of your passwords and the information that is stored in a visitor’s cookies. It is super easy to do as well!

  1. Head to WordPress Salt Keys Generator
  2. Copy the code provided
  3. Replace the corresponding code in the wp-config.php with the keys you have copied

Disable File Editing Within WP Dashboard

If your admin account does become compromised or one of your upper level employees has gone rogue, disabling file editing permissions within the WP Dashboard is a great way to prevent further destruction. You can simply add the following to the WP-Config.php file:

define('DISALLOW_FILE_EDIT', true);

Disable Theme & Plugin Installation

Once your website is completely setup and ready-to-go, we recommend disabling the ability to add, delete or modify website themes and plugins from the WP Dashboard. You can easily do this by adding the following line of code to your wp-config.php:

define( 'DISALLOW_FILE_MODS', true );

Prevent Directory Snooping

WordPress & Plugins do a superb job of adding a blank index file to the directory tree. But to be safe, we recommend you disable indexes. You can easily do this by adding the following line of code to your .htaccess file:

Options All -Indexes

Protect .htaccess file

Protecting your website's .htaccess files is critical to maintaining a secure environment. You can easily do this by adding the following to your web root .htaccess file:

<Files ~"^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>

WP Version Removal

By default, WordPress will place a meta tag in your website code that states the version of WordPress you are using. This can be used against you if your running version has publicly known vulnerabilites listed. You can easily disable this by adding the following line of code to your themes functions.php file:

remove_action('wp_head', 'wp_generator');

Routine Backups

Besides falling victim to a hack, accidents do happen. It is best to routinely backup everything including files and database tables. This way if you do get hacked or a developer pushes bugging code live, you can easily roll back to a functional version of your website!

Intermediate Level Security

Onion Defense

We titled this section onion defense, because it adds another layer of security. We recommend the CloudFlare service as it is great at improving your performance as well as security.

It may be a tad bit difficult for beginners to setup, but you route your DNS through CloudFlare and they filter out malicious traffic before it even touches your website. They can protect you from denial of service attacks, SQL injections and known hackers.


Database Prefix

By default, during a WP Installation, the prefix wp_ is loaded. We recommend you change this. While performing an SQL injection attack, hackers will try the wp_ prefix first. And with the WP database table structure being widely known, you’re making it easy for hackers by using the default setting.

If you need to change a live websites table prefix you need to alter every single table AND update the $table_prefix variable in the wp-config.php file. We recommend briefly throwing up a maintenance page.


Lock Down WP-Login

If you or your team are the only ones who log into your WP website, it is best to completely lockdown the wp-login.php page. This can be easily done by adding the following to your .htaccess file:

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

Simply replace xxx.xxx.xxx.xxx with whatever IP addresses need access to the login page. The above code will block access to everyone except those IP addresses.

Another solution would be to lock down the /wp-admin/ directory by adding another layer of authentication utilizing the .htpasswd file in conjuction with .htaccess. You can use this tool to generate an .htpasswd file if you don’t know how. Upload the .htpasswd file to your web server, add and alter the following in the .htaccess file within the /wp-admin/ directory:

AuthName "Admins Only"
AuthUserFile {FULL HTPASSWD PATH HERE}
AuthGroupFile /dev/null
AuthType basic
require user {USERNAME HERE}

An example for {FULL HTPASSWD PATH HERE} would be: {DIR}example.com/.htpasswds/public_html/wp-admin/passwd


Protect WP-Includes

If you are on a linux machine and have access to your .htaccess configuration file, add the following to it:

# Block the include-only files.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

This will protect your WP-Includes files from unauthorized access.


Protect WP-Config

The WP-Config.php file defines database connection credentials. If this file were to ever become compromised, it can put you at serious risk. It is possible for the PHP engine to fail and accidentally display http://{yourdomain}/wp-config.php as plain text rather than a white screen.

We have two suggestions for protecting this very important file and just completely blocking out access to it.

Easy Method - Protection via .htaccess

Add the following to your .htaccess file

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

Difficult Method - Move WP-Config.php Outside Web Root

Your website root directory is typically defined by a virtual host file on the LAMP stack. You may need to configure open_basedir but we recommend moving the WP-Config.php file ONE directory above your website root.

WP automatically scans ONE directory level above the web root folder, but you're also able to move it anywhere and define where to find it by editing the Index.php file:

<?php

/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');

/** Location of your WordPress configuration. */
require_once(ABSPATH . '../{SPECIAL_DIR_HERE}/wp-config.php');

File Permissions & User Groups

A huge security flaw in many plugins is that they rely on unnecessary write access permissions. If you chmod your wp-content/uploads folder to 0777, you are vulnerable, do not listen to that plugin.

All files should be 0644 and all folders should be 0755. As long as you have the proper user and group setup, your website will function fine and securely. They must match whatever usergroup your web server is operating under.

Complex Level Security

Multi-Factor Authentication

Two-Factor Authentication [TFA] and One-Time Password [OTP], have grown in popularity over the years! Although very similar, many of the most highly used apps and websites offer TFA or OTP as an option. You have the option to build these into your WordPress platform as well.

Two-Factor Authentication

There are multiple TFA plugins out there that will help you easily implement this feature. Upon login attempt, you will typically have to confirm your identity via a passcode that is sent via text message or email.

One-Time Password Authentication

We're fans of YubiKey but I'm sure there are other brands out there that are just as good. With our YubiKey - we can go to the WordPress login page, insert out YubiKey into our USB port on our computer and press the OTP button and it will log us in. So easy for the user, so difficult for the attacker. The attacker will need to physically have your YubiKey!


Restrict Database User Privileges

WordPress only needs: Select, Insert, Update and Delete privileges during normal operation. It is best to only apply these privileges in a production environment. Unrestricted access can lead to dropped or emptied tables and just complete dataloss. If you’re not routinely backing up your data, a loss can be detrimental to your business or creative work.


Database & WordPress Separation

Best practice for security & performance is to keep your database server and your web server separate. This will hopefully limit damage if you do indeed become compromised. It also inadvertently increases website performance since you have more resources dedicated to each service.

With the power of cloud technology, this has become far easier to accomplish in recent times. You can easily spin up a database or web server instance on many popular Cloud providers like Amazon Web Services, Microsoft Azure & Linode.


NGinx Reverse Proxy Server

The ultimate method is a bit complex. Bare with me...

You have your:

  • Apache Web Server
  • MySQL Database Server
  • NGinx Reverse Proxy Server

What you need to do is completely lock-down your apache web server & MySQL database server. Completely block access to both these servers from the outside world except for port 22 which you'll need for Shell & SFTP access.

Always use varying root password credentials for all of these servers. In the unfortunate event that one does become compromised, you can swiftly lock-down the other two. For the web & database servers, we recommend the following:

  • Enable mod_security on the Apache Web Server
  • Configure mysql_secure_installation in the shell

For CentOS 7 specifically, you will need to enable the apache server to access the database server by running the following command:

setsebool -P httpd_can_network_connect=1

You will need to configure the MySQL Database Server to only allow connections from your Apache Web Server, typically port 3306. You then need to configure your Apache Web Server to only allow connections from your NGinx Reverse Proxy server on ports 80 & 443. This locks down your environment. Your actual web server and database are technically not even connected to the internet. The only access is through a highly guarded door.

The "highly guarded door" will need to be completely customized and secured. Depending on your project and the functionality you require, we suggest the following:

  • Completely block out root, control panel, SFTP, etc... access except from your internal network
    • If you need to perform work on the go, you will need to remote desktop into your internal network
  • Enable Security-Enhanced Linux (SELinux) & Do Boolean Lockdown
  • Linux Kernal Hardening (/etc/sysctl.conf)
    • Avoid log spoofing, smurf attacks, reverse path filtering and more
  • Configure IP Tables to be extremely restrictive
    • Throttle end users before accessing your nginx server
    • Deny access from any countries you have no business in
  • Remove Any Unneeded Nginx Modules
  • Limit Buffer Overflow Attacks via nginx.conf
  • Limit Number Of Connections - Use the NginxHttpLimitZone Module
  • Allow requests to only your domain - block all other scans & hits
  • Restrict Outgoing Nginx Connections
  • Throttle Nginx Connections Per Second