How to Audit WordPress Security at Every Layer
By WP Vanguard Team
Ask someone to audit a WordPress site's security and they'll almost always start, and stop, in the same place: check plugin versions, look for weak passwords, maybe run a malware scan. That's real work, but it covers one layer out of three. The network in front of WordPress and the server underneath it get skipped because they don't feel like "WordPress problems". Attackers don't share that assumption.
This guide walks through all three layers in order, with the settings to check at each one. It replaces three shorter guides we published separately (network, hosting and the overview), because the layers only make sense together: each one can undo the work you did on the others.
Key finding
Audit from the outside in: network edge first, then the server, then WordPress itself. A leaked origin IP lets an attacker walk around a perfectly patched site.
The three layers at a glance
| Layer | What it covers | Where you check it |
|---|---|---|
| 1. Network edge | DNS, CDN and WAF, TLS, security headers | From outside, no server access needed |
| 2. Server | Account isolation, PHP, SSH, database, uploads, backups | Shell access on the host |
| 3. WordPress install | Core, plugins, themes, users, file integrity | WP-CLI or the dashboard |
Layer 1: The network edge
This is everything between a visitor and your server. It's the first thing an attacker touches and, done right, the place where most automated attacks stop before WordPress sees a single request. A plugin vulnerability scan can't see any of it.
Hide your origin IP address
If your domain is proxied through Cloudflare (the orange cloud) but an old DNS record still points straight at your server's real IP, an attacker who finds it can skip your WAF and hit the origin directly.
- Check every DNS record, not just the main
Arecord. Staging subdomains, mail records and oldwwwentries are the usual leaks. - Proxy every record that serves web traffic. Leave DNS-only (grey cloud) only the records that must resolve directly, such as
MX. - Configure the server firewall to accept web traffic on ports 80 and 443 only from Cloudflare's published IP ranges. This one step makes a leaked origin IP useless.
- If the IP has already leaked, look for direct hits in your server logs, and rotate to a new IP where your host allows it.
Configure the WAF and CDN
A CDN set to "DNS only", or a WAF whose rules aren't tuned for how WordPress works, does nothing for security.
- SSL/TLS mode: Full (Strict). Flexible mode encrypts only the visitor-to-Cloudflare leg and leaves the leg to your origin in plaintext. Full (Strict) needs a valid certificate on the origin and encrypts both.
- Always Use HTTPS, so any HTTP request is redirected before it reaches WordPress.
- Managed WAF rules for WordPress. Cloudflare's free tier includes a WordPress ruleset. Turn it on rather than relying on the generic rules.
- Rate limit
/wp-login.phpand/xmlrpc.php. These two endpoints take most of the automated login and amplification attempts. A rule limiting each IP to a handful of requests a minute stops that traffic before WordPress processes it. - Bot Fight Mode or a bot rule, so scripted scanners get challenged instead of walking through.
Harden TLS
A certificate that exists isn't the same as one that's configured well.
- Require TLS 1.2 as the minimum and disable TLS 1.0 and 1.1 if your CDN still offers them.
- Enable HSTS (
Strict-Transport-Security) so browsers refuse to fall back to HTTP. Start with a shortmax-ageand raise it once you've confirmed nothing breaks. - Add a CAA DNS record that limits which certificate authorities may issue certificates for your domain.
Set security headers
Most WordPress installs ship with none of these, and a CDN can add them at the edge with no plugin and no code change.
X-Content-Type-Options: nosniffstops the browser guessing content types in ways that can be abused for XSS.X-Frame-Options: SAMEORIGIN(or aframe-ancestorsCSP directive) stops your login page being framed for clickjacking.Referrer-Policy: strict-origin-when-cross-originavoids leaking full URLs, including query-string tokens, to third-party sites.Content-Security-Policyis the most powerful and the easiest to get wrong. Start in report-only mode, watch what breaks, then enforce it.
Clean up DNS hygiene
- Turn on 2FA and a registrar lock at your domain registrar. Domain hijacking through a compromised registrar login has nothing to do with WordPress, and it takes the whole site.
- Enable DNSSEC if both your registrar and DNS provider support it.
- Remove stale DNS records for services you no longer use. Every forgotten subdomain is a possible origin leak or a subdomain-takeover target.
If you're starting from nothing, work in this order: proxy the DNS records and lock the origin firewall to CDN addresses, then set TLS to Full (Strict) and enable HSTS, then rate-limit the login endpoints, then add the headers. Each step closes a gap the previous one left open.
Layer 2: The hosting and server
This is the machine WordPress runs on, and it's invisible to any scan that only talks to your site over HTTP. A WordPress install can be perfectly configured and still be compromised because the server underneath runs an end-of-life PHP version, allows password SSH logins, or lets PHP execute inside the uploads folder.
Isolate every site
Shared hosting that puts several WordPress installs under one system user turns one compromised site into a compromised server. If a plugin bug lets an attacker write a file, and every site shares file permissions, they can reach all of them.
- Each site should run under its own system user, with
open_basedirlimiting PHP to that site's directory. - On your own VPS, don't host more sites than you can keep patched. A neglected fifth site is how the other four get breached.
- Ask your host directly whether accounts are isolated. Cheap shared hosting often isn't, and no WordPress plugin can fix that.
Keep PHP current and locked down
- Run a PHP version that still gets security updates. An end-of-life PHP has unpatched flaws in the language runtime itself.
- Set
disable_functionsto block functions WordPress doesn't need and malware relies on, commonlyexec,shell_exec,proc_openandpassthru. Test on staging first, because some backup and caching plugins use them legitimately. - Turn
display_errorsoff in production. A stack trace tells an attacker your file paths, plugin versions and sometimes your database structure.
Lock down SSH and server access
- Key-only authentication. Disable SSH password login so a leaked or guessed password can't get in.
- No root login over SSH. Use a named account with
sudo, so every login is attributable. - Fail2ban or an equivalent, to block IPs after repeated failed attempts. It's the SSH equivalent of rate-limiting
wp-login.php. - Restrict SSH to known IP ranges where practical, or at least move it off port 22 to cut the background noise of automated scans.
Harden the database
- MySQL or MariaDB should bind to
localhostor a private network only. It has no reason to accept connections from the public internet. - Use a dedicated database user per site, with privileges limited to that site's database. Don't reuse one root-equivalent account across every install.
- Rotate database credentials if you ever suspect a leak, the same way you would any compromised password.
Stop PHP executing in uploads
The uploads directory should hold images, PDFs and media, never executable code. Most successful WordPress compromises drop a PHP backdoor into wp-content/uploads/ because it's writable and, on a misconfigured server, still executable. Block it at the server, not with a plugin:
# nginx
location ~* /wp-content/uploads/.*\.php$ {
deny all;
}
# Apache (.htaccess inside wp-content/uploads/)
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
Watch out
A clean uploads folder today doesn't mean it stays clean. Re-check it on a schedule for PHP files that don't belong.
Back up like you expect to need it
A basic checklist says "set up backups". These are the parts that make a backup useful when you need it.
- 3-2-1 at minimum: three copies, on two kinds of storage, with one off the server. An on-server backup goes down with the server.
- Database and files on separate schedules. The database changes constantly, so back it up daily. Files change less, so weekly is often enough unless you publish a lot.
- Test a full restore at least once, ideally on staging. A backup nobody has restored is a hypothesis, not a safety net.
- On a VPS, pair application backups with host snapshots. A snapshot restores the whole server state, configuration included, which a database dump can't.
Watch the server, not just the site
- Review SSH auth logs now and then for unfamiliar IPs or repeated failures from one source.
- Watch for unexplained CPU or disk spikes, a common sign of a cron-based backdoor or a cryptominer dropped through a plugin.
- Audit cron at the system level, running
crontab -lfor every user, not just WordPress's ownwp_cron. A malicious entry that re-downloads a backdoor every hour survives a WordPress-only cleanup.
Layer 3: The WordPress install
This is the layer most audits already cover, and it still deserves a proper pass. With WP-CLI on the server, each check takes a line.
Versions. Core, plugins and themes should all be current, and anything abandoned should go.
wp core version
wp plugin list --fields=name,version,update
wp theme list --fields=name,version,update
Then check what you run against known disclosures. Our guide to checking plugins against known vulnerabilities covers how, and the weekly patch list shows what's being attacked right now.
Users. List every administrator and ask whether you recognise each one. An admin account you didn't create is a finding.
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
File integrity. WordPress publishes checksums for core and for plugins from the directory, so modified files stand out.
wp core verify-checksums
wp plugin verify-checksums --all
Premium plugins and themes have no public checksums, which is where a malware scan earns its place. If anything looks wrong, our guides to signs your site has been hacked and PHP backdoors in WordPress show what to look for, and the malware removal guide covers cleanup.
Configuration. Check that wp-config.php isn't readable from the web, that file editing is disabled in the dashboard with DISALLOW_FILE_EDIT, and that the rest of the security checklist is done.
Why the order matters
A misconfigured network layer can undo hardening at the other two. A leaked origin IP lets an attacker bypass your WAF and hit a patched WordPress install directly. A weak server layer can undo application fixes too: DISALLOW_FILE_EDIT doesn't matter if PHP can execute in the uploads folder regardless.
Fixing layer 3 alone closes the door WordPress controls and leaves the other two open. That's why we audit from the outside in.
Running the full audit in three passes
- Check the edge. DNS records, TLS mode, WAF rules and headers. You need no server access, only tools that see your site the way a visitor or an attacker does.
- Check the server. SSH, PHP settings, database exposure, upload execution and backups. This needs shell access, which is why most surface scanners skip it.
- Check the install. Versions against known vulnerabilities, the admin list, file integrity and malware signatures.
WP Vanguard's free surface scan covers most of layer 1 (TLS, headers, exposed paths, WAF and CDN detection) without any credentials. The deep scan connects over SSH and covers layer 3 fully, plus the parts of layer 2 visible from inside the server: PHP version, file permissions, uploads execution and cron integrity.
It doesn't replace asking your host about account isolation, or locking down your registrar, because those decisions sit outside anything a scan of the server can see. What it does is tell you, in one pass, which of the three layers still needs attention.
Related reading
Check Your WordPress Site Security
Free scan, no login required. Find vulnerabilities before attackers do.
Scan Your Site FreeGet weekly WordPress security tips
Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.