The Wordfence trap
We see it every week. A site gets compromised. The owner installs Wordfence, runs a scan, removes the obvious malware, and considers the problem solved. Three months later the same site is compromised again β sometimes by the same attacker using the same backdoor that the plugin never detected.
A security plugin is one layer of defense, not a security strategy. The sites that don't get re-compromised run six layers in parallel. Below is the architecture we deploy for clients in WooCommerce, membership sites, and any business where downtime costs real money.
Layer 1 β The server itself
WordPress runs on top of an OS, a web server, a PHP runtime, and a database. If those are weak, no plugin can save you.
Minimum baseline
- SSH key authentication only, password login disabled
fail2banon SSH, web logs, and SMTP (if applicable)ufworfirewalldallowing only the ports you actually use- Unattended security upgrades enabled
- A non-root sudo user, never working as root
- File system: separate partitions for
/var/wwwand/tmpwithnoexecon/tmp - Outbound SMTP locked down (only your relay can use port 25)
The most common breach we forensically trace doesn't start in WordPress at all β it starts with a shared host where a sibling site got compromised and the attacker pivoted via the file system.
Layer 2 β The WAF
A Web Application Firewall sits between the visitor and WordPress, blocking attacks before any PHP runs. The right WAF stops 90%+ of automated attempts without ever bothering your server.
What a real WAF blocks
- Brute force on
/wp-login.phpand/xmlrpc.php - Known plugin CVE exploit signatures
- SQL injection patterns in query strings and bodies
- File inclusion attempts (
?file=../../etc/passwd) - REST API endpoints used in unauthenticated user creation attacks
- Excessive POST requests from a single IP
Options that work
- Cloudflare Pro ($20/month) with the WordPress managed ruleset enabled
- Sucuri WAF if your hosting doesn't expose IP-level config
- Self-hosted ModSecurity with the OWASP CRS and WordPress rules for VPS users
Wordfence's WAF is a "plugin firewall" β it runs inside PHP, after the attacker has already reached your application. It's better than nothing, but it can't stop attacks that crash PHP before reaching its hooks.
Layer 3 β WordPress hardening
Once an attacker is at the WordPress layer, internal hardening becomes the difference between a noisy attempt and a successful breach.
The non-negotiables
- File permissions: directories 755, files 644,
wp-config.php600 DISALLOW_FILE_EDITset totrueinwp-config.php(no theme editor)DISALLOW_FILE_MODSset totrueif you deploy code via git- Salts in
wp-config.phprotated quarterly - Strong database user passwords; the WordPress DB user should not have GRANT privileges
xmlrpc.phpblocked at the web server level (unless you use Jetpack)- REST API
/usersendpoint restricted to authenticated requests
What we always remove
- The default
adminusername (if it exists, we create a new admin and delete it) - The "Hello world" post and sample comment (low-grade fingerprinting clues)
readme.htmlandlicense.txt(version disclosure)- Inactive themes and plugins (every dormant plugin is an attack surface)
Layer 4 β Identity and access
The majority of WordPress breaches we see in 2026 don't involve a software vulnerability β they involve credentials. A user clicked a phishing email, reused a password, or the attacker brute-forced through a weak admin pool.
Identity controls that actually work
- 2FA mandatory for all administrator and editor roles
- Time-based codes (TOTP) preferred over SMS
- Backup codes printed and stored offline
- Login restricted to known IP ranges via the WAF (if your team works from fixed locations)
- Session timeout reduced from default 14 days to 24 hours for admins
- All inactive accounts disabled, not deleted (preserves audit trail)
The Application Passwords trap
WordPress 5.6+ shipped Application Passwords for REST API access. Attackers know this. We disable Application Passwords for every role except those that genuinely need API access, via the wp_is_application_passwords_available filter.
Layer 5 β Monitoring
Defense isn't enough. You need to know when something gets past the perimeter β within minutes, not weeks.
The four monitors we always set up
- File integrity monitoring β alerts when any file in
wp-contentchanges outside a deploy. We usetripwire,aide, or a custom inotify watcher. - Log aggregation β Nginx, PHP, MySQL, and WordPress audit logs centralized so suspicious patterns are visible.
- Outbound request monitoring β a compromised site usually starts making outbound POSTs to attacker C2 servers. We watch egress for anomalies.
- External uptime + reputation β UptimeRobot for downtime; periodic checks against Google Safe Browsing, Spamhaus, and Sucuri SiteCheck.
The alert routing matters: file changes go to Slack within 60 seconds, blacklisting alerts go to email and SMS within 5 minutes.
Layer 6 β Backups and tested recovery
The final layer is the one most owners get wrong. "I have backups" is meaningless unless you've tested restoring them. We've seen daily backups go untested for months and turn out to be corrupted when finally needed.
A real backup strategy
- Off-server location (S3, Backblaze, or a different data center)
- Encryption at rest (AES-256 with the key not stored on the same server)
- Retention: daily for 14 days, weekly for 12 weeks, monthly for 12 months
- Database dumps using
mysqldump --single-transactionto avoid corruption - A monthly restore drill on a staging server β this is the only proof that backups work
Recovery time objectives
For a serious business site we target: - RTO (recovery time objective): under 30 minutes for full restore - RPO (recovery point objective): under 4 hours of data loss
Anything looser than that is fine for hobby sites β not for a business that depends on the site.
Common mistakes we still see in 2026
- Wordfence + nothing else β fast plugin scan + no server hardening + no WAF in front
- Backups on the same server β when the server is compromised, the backups go with it
- 2FA only on the main admin β attackers create a new admin (no 2FA enforced) and bypass
- Vendor lock-in for migration backups β using a plugin that produces backups only restorable by the same plugin
- Disabled file integrity monitoring because "it's noisy" β without it you literally don't know when malware lands
When to call a specialist
If you've been breached more than once in 12 months, the issue isn't the malware β it's the absence of layers. We deploy this stack for clients in WordPress recovery and harden every layer in a way the original attacker can't replicate.
Hacked website repair covers post-breach cleanup. WordPress emergency support handles active incidents. Malware removal digs into infections with forensic depth β and yes, we close the entry point too.

