Securing WordPress in The Enterprise

Approaching a web applications security is as much about mindset as it is about the tools and configurations you deploy. It’s why security professional always talk about people > process > technology. Unfortunately, in almost every incident response instance the former components, of people and process, are often nonexistent.

I blame a lot of this on the noise that exists around securing your web applications. To help, let’s get focused.

We will use the WordPress Content Management System (CMS). It’s popularity with bad actors, and the internet as a whole, makes it an easy platform to focus on.

This is our approach to securing WordPress. You will notice that our approach to security is not about configuring every possible option, but focused on the three key things we’re working to prevent. Those three things are at the core of how most compromises occur.

Simplifying Security with Focus

If you spent any time helping an organization conform to any regulatory standard, you quickly realize that the key to successfully achieving compliance is to manage scope. The greater the scope, the more difficult it is to achieve compliance. The more focused, the easier it is.

Our approach to securing WordPress leverages this thought process when building a security strategy for our web applications. It is built out of a basic framework.

These three tenants are foundational to how, and what, we deploy when securing our applications:

TenantDescription
AccessLimit access across the stack to known, trusted, sources.
FilesLimit, and know, what files exist, what is modified, and what is introduced.
MovementLimit potential damage by controlling what can be accessed in the event of a breach.

Focusing on these areas will dramatically offer you the ability to deploy effective defensive controls, reducing the noise, and allowing you to focus on what matters. This basic framework is built on a decade of remediation’s and focuses on what bad actors require to be successful.

Step 1. Access

Controlling access is more than 50% of the battle in almost every application deployment. It’s ironic because it’s the #1 targeted vector abused by automated, and non-automated, attacks and it’s almost left wide-open to the world.

The biggest issue with tackling access is it requires behavioral change. We have to educate our non-technical users that a) not everyone needs access, and b) that no everyone requires administrative access.

When thinking a about Access, there are two areas to focus on:

Focus AreaDescription
ApplicationHow do you log into the application? WordPress uses /wp-admin and /wp-login.php to access the friendly administrative panel.

Defensive controls to harden these:
– Browser authentication
– IP authentication (i.e., whitelist approach)
– Multi-Factor Authentication (i.e., Google Authenticator)
– Least Privileged principles (i.e., everyone doesn’t need to be an administrator)
ServerHow do you log into the server that houses the application? Are you using FTP/SFTP/TELNET/SSH?

Defensive controls to harden these:
– IP authentication (i.e., whitelist approach)
– Multi-Factor Authentication (i.e., YubiKey)
– Remove insecure modes of connection (i.e., FTP / TELENT)
– Least Privileged principles (i.e., everyone doesn’t need to be an administrator)
– Key authentication in the place of password authentication

We would be remised if we didn’t mention the importance of passwords. Use randomly generated passwords and a password manager, and educate your organization on it’s use. The fact, however, remains that you will still have users that believe themselves low risk and will go through all the training, but still use “password”. The controls above will help reduce the self-imposed risk they introduce to your organization.

I personally place a lot of focus on Access because it’s a) the #1 attack vector, ahead of vulnerabilities being exploited, and b) it’s the one thing that can be done to dramatically reduce the noise on your application and server environments.

It also happens to be one of the easiest things to fix.

We have found using a whitelist approach to authentication is by far one of the most effective hardening techniques an organization can deploy. I provide a very simple IP Authentication script on GitHub that leverages the IP authentication feature in NOC for accessing servers.

We also offer a browser based authentication mechanism here at NOC.org, try accessing noc.org/wp-admin and you’ll be greeted with this:

You can achieve a similar, IP vs Browser authentication, experience using .htaccess:

RewriteCond %{REQUEST_URI} ^(.*)?wp-login\.php(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^(.*)?wp-admin$
RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$
RewriteCond %{REMOTE_ADDR} !^234\.234\.234\.234$
RewriteRule ^(.*)$ - [R=403,L]

Step 2. Files

Files is a very broad category, but I break it down into the following areas:

TypeDescription
NewI don’t want new files added to my installation without my approval.
ManipulatedI don’t want files that exist to be manipulated without my approval.
ExecutedI don’t want files to be executed unnecessarily

Look at every hacked website and one thing will always stand true – bad actors will work to introduce, or manipulate, files to achieve their desired outcome. It’s why you see so many attacks manipulate .htaccess, index.php, header.php, function.php, or add new backdoors to a WordPress site.

The manipulation of files allow them to inject malicious payloads to distribute malware, while the introduction of backdoors gives them access long after you have locked down the access.

So to stop the introduction of new files, and the manipulation of existing files, we always focus on the files ownership. To prevent this outright in WordPress we remove writability to core and it’s directories. We do this by creating a user dedicated to the install. For instance, for this site, this is what it would look like:

# adduser noc
# chown noc:noc /var/www/noc.org
# chown -R noc:noc /var/www/noc.org/*

We make sure the user is not part of the NGINX or APACHE usergroup, and leave the site in this state until an update is required.

This small change prevents the introduction of changes to your WordPress instance. It does not prevent you from writing, or making updates, to pages and posts, but does ensure that the integrity of your install stays in tact. Whether intentional, or unintentional.

The only directory that does need to be writeable is the /uploads directory. That is where all your images go when you use the media library. It’s also the one directory that poses the most risk; it’s where most payloads are injected:

# chown www-data:www-data /var/www/noc.org/wp-content/uploads/

It’s why you always want to remove the ability to execute PHP in this directory:

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

This ensures you don’t lose the ability to upload files, but limits the ability to execute a file if it’s been uploaded with malicious intent.

This configuration has the added benefit of hardening, protecting, against supply chain attacks as well.

Step 3. Movement

This one has been a personal focus area, and it speaks to lateral movement in an environment. Or said differently, the ability for a bad actor to move in your environment and infect neighboring sites.

One way bad actors do this is to use backdoors, like the one we addressed in Step 2, and disabling PHP execution does a good job of addressing this risk.

The other, however, is when the bad actor has access to the server itself and has the ability to move “laterally” within the environment. Our personal preference is simple, functional isolation.

NameDescription
Functional IsolationClearly defining the purpose of a system, and explicitly configuring the platform for that purpose.

You could argue that the “web server” is a very specific purpose, as such having multiple sites on it is ok. You would be right, but I would still encourage you to place special emphasis to reduce the exposure to that server by limiting what you host on a server. Where possible, we always recommend a dedicated server for each application. The current state of technology makes this approach extremely achievable and affordable, especially if you’re an enterprise.

I prefer a 1:1 relationship between server and web applications because it’s just too easy to get it wrong. There are absolutely other solutions like using chroot, FPM, etc.. but that doesn’t do away from other privilege escalation vulnerabilities that you must now be aware of and account for on the server itself.

For me, it’s not worth the risk when it comes to key platforms.

WordPress Security Simplified

WordPress Security doesn’t have to be complicated. Unfortunately, we’ve convoluted the entire conversation with our top 10 recommendations, and tips and tricks that yield 150 different recommendations. But the reality is that there are only two attack vectors abused most often by bad actors: access control and software vulnerabilities, both are addressed by the recommendations in this post.

The three steps above are at the core of every WordPress deployment we have managed, and have helped remediate over the past decade. They are the most effective hardening tips available for any WordPress installation, especially if it’s an enterprise level application.

Another defensive control worth investigating is a Web Application Firewall (WAF). This technology filters malicious requests at the edge, keeping them from ever hitting your web server or application. They have the ability to patch things faster than most organization, and dramatically reduce the impact of conflicts and downtime while giving an organization peace of mind.