Recent research from WeWatchYourWebsite based on data from millions of WordPress sites has shown that 67% of all WordPress compromises are caused by either session cookie hijacking or stolen credentials.
Additionally, plugin vulnerabilities related to privilege-escalation are consistently among the most mass-exploited:
- Patchstack: Critical Elementor Pro Vulnerability Exploited (March 2023)
- Patchstack: Critical Privilege Escalation in Essential Add-ons for Elementor (May 2023)
Regardless of how an admin account is compromised, for the vast majority of WordPress sites, it is game over for the site (and if the attacker is somewhat skilled, the server too).
Attackers will immediately use the admin access to execute arbitrary PHP code by uploading a malicious plugin or by editing the theme/plugin files. This then usually leads to RCE (remote code execution) via a reverse shell.
In the WP ecosystem, the threat model usually stops at the point of a compromised admin account, the common mindset of agencies and vendors being something like:
Oh well, if an admin account is compromised, there’s nothing we can do.
This is crazy and practically unheard of in other mature software ecosystems.
In our opinion, it is unacceptable to build web applications with WordPress (LMS, E-Commerce, Membership etc.) or anything remotely important to a business with this mindset.
A compromised admin account is bad, yes.
But an authentication breach MUST be contained at the authentication/user level, instead of immediately leading to a full compromise of the site/server.
That’s what defense-in-depth is all about.
By allowing plugin & theme installation and other code modifications in production, you’re inviting the worst kinds of exploits that are extremely difficult to recover from, such as:
- Escaping site isolation to a root compromise of the server (A medium skilled attacker will be able to do this on most WP hosting platforms).
- Sending huge amounts of spam using your SMTP credentials.
- Mining bitcoin using your server resources.
- Attacking other sites from your site, which will get your IP blacklisted and the server taken down.
- Dumping your entire database or writing arbitrary data to it.
- Revealing all sensitive data from the server’s file system.
- Encrypting your site/database/backups and demanding a ransom.
- Creating very hard to detect backdoors with fileless malware.
- Preventing you from restoring backups and recovering fast.
- etc.
None of this would have been possible with a proper separation between an admin account compromise and the ability to change the running code of the site.
That’s why every single enterprise-hosting company deploys immutable file systems in production, where no code can be changed.
That’s how it should be ideally. After all, WordPress is a CMS, and not a file manager.
To add insult to injury, on most WordPress sites, the ability to install new plugins is completely unneeded after the initial site build is complete – except on rare occasions.
Sure, you might update your existing plugins & WordPress core, but how often do you add brand-new plugins that are not in your boilerplate stack?
We recently created a poll asking WordPress agencies:
“On average, how often do you ADD or REMOVE (disable/delete) plugins after a site’s build is finished, and the site is running smoothly in production.”
All of this is already a solved problem in the enterprise hosting world, where everything is version-controlled and deployed from a CI/CD system.
But the (sad) reality is that this will be forever out of reach for 99.99% of WordPress sites for various reasons including cost & complexity.
That’s why we added Code Freeze to Fortress, which gives you 80% of the benefits of an immutable deployment strategy, with almost none of the complexity.
How it works
Code Freeze adds significant defense-in-depth against attackers who have gained access to an administrator (or similar) account through any means.
It doesn’t matter how they got in, and that Fortress’s Auth and Session modules already make it very extremely difficult to compromise an account without a zero-day.
That’s what having multiple layers of defense is all about – Redundancy & Fault Tolerance.
Code Freeze detects if your site is running in production and ensures that:
- No new plugins/themes can be installed from the repo.
- No plugins/themes can be uploaded.
- No files can be edited.
- No plugins can be deactivated & themes can’t be switched.
However, you can still (auto) update any existing plugin, theme or core from within the admin dashboard and WP-CLI.
You get the easy maintenance and convenience of updating your plugins right from the dashboard, but without the security risks that unrestricted plugin uploads bring with a compromised admin account.
It’s the best of both worlds.
Furthermore, via a tight server-side hosting integration, Code Freeze immediately detects when it runs in a staging environment where you can then freely upload plugins & themes again.
As an example, after we push our Fortress site to staging on GridPane:
We can immediately add new plugins and/or remove existing ones.
It’s okay to install plugins on staging sites, as they can generally be locked-down much easier than production sites by putting them behind HTTP basic auth or IP whitelists.
And independently of the security aspect, it’s just a general development best practice.
- Push to staging.
- Install new plugins & confirm that everything works.
- Push back to production.
When you push back to production, Code Freeze immediately re-applies the restrictions again without any action required on your part.
Does this work on dynamic sites?
Yes, Code Freeze works on dynamic sites such as WooCommerce, LMS, membership, etc.
What does Code Freeze cost?
Code Freeze is immediately available to all direct & hosting Fortress customers at no additional cost.
How do I install the occasional new plugin?
The recommended workflow is using staging sites and the classic workflow of:
- Push to staging.
- Install plugin(s) and test.
- Push to production
If you don’t want to use a staging environment, you can:
- a) Install any wp.org plugin using WP-CLI.
- b) Upload free and “pro” plugins via (S)FTP and then activate them via the admin dashboard.
- Temporarily disable Code Freeze (depends on your hosting integration).
I hate this & want to keep cowboy-coding, can I disable Code Freeze?
Yes, Code Freeze is a new module in Fortress that is completely independent of all other functionality.
Where can I find more information?
Refer to the full technical docs on GitHub.
4 responses
You didn’t see me fall off my chair, but I just did. Amazing work!
Love this feature! We very rarely add new plugins after launch, so this is a no-brainer.
Totally awesome.
Fortress keeps getting better. I’m so grateful for the people behind this. My online film school can’t handle downtime due to malware and the like!