WordPress security isn't about installing a plugin and hoping for the best. I've cleaned servers where attackers embedded cryptominers with 14 separate persistence mechanisms. I've investigated breaches where admin accounts were created through control panel vulnerabilities. I've removed malware that hid from ps, survived reboots, and re-downloaded itself from command-and-control servers. These experiences have shaped how I approach security — proactively, at every layer, with the understanding that prevention is always cheaper than cleanup.
I'm Michal, a UK-based WordPress developer at Rootscope. I manage security for 70+ WordPress sites and the servers they run on. My security service covers everything from hardening your WordPress installation and server environment to monitoring for threats, responding to incidents, and recovering from breaches.
The best security incident is the one that never happens. Most WordPress compromises exploit predictable weaknesses — weak passwords, outdated plugins, unnecessary admin accounts, and servers running default configurations. I eliminate these before attackers can.
Two-factor authentication enforcement across all admin and editor accounts. I don't recommend 2FA — I require it. SMS-based 2FA is not acceptable; I deploy TOTP-based authentication (Google Authenticator, Authy, or similar) because SMS can be intercepted via SIM swapping. For agencies managing multiple sites, I integrate 2FA with their existing identity management workflow.
Strong password policies enforced at the WordPress level and on the server. Minimum length, complexity requirements, and forced rotation for privileged accounts. I also audit for passwords that have appeared in known breach databases using the Have I Been Pwned API. You'd be surprised how often an admin password on a production WordPress site shows up in a data breach dump.
Plugin and theme auditing is an ongoing process, not a one-time check. I review every plugin on a site for known vulnerabilities using the WPScan vulnerability database, check for plugins that have been abandoned by their developers (no updates in 12+ months), identify plugins that introduce unnecessary attack surface (file managers, code editors, database admin tools), and remove anything that isn't actively needed. Every plugin is an entry point. Fewer plugins means fewer ways in.
User account hygiene — I audit user accounts for dormant admins, shared logins, and excessive privileges. A contributor doesn't need admin access. An intern who left six months ago shouldn't still have an account. I enforce the principle of least privilege and set up account review schedules.
Login hardening — rate limiting on login attempts, IP-based restrictions for wp-admin where practical, XML-RPC disabled unless specifically required, and REST API endpoint restrictions. These are basic measures that stop the vast majority of automated attacks.
WordPress security starts at the server. A hardened WordPress installation on an unhardened server is like putting a deadbolt on a door with no walls.
Firewall configuration using UFW or firewalld with a default-deny policy. Only ports 80, 443, and a non-standard SSH port are open. Database ports are never exposed to the internet. For multi-site servers, I configure per-site isolation where possible so that a compromise of one site doesn't automatically give access to others.
SSH hardening — key-based authentication only, password login disabled, root login disabled, non-standard port, and Fail2ban monitoring for brute force attempts. These four changes eliminate the vast majority of SSH-based attacks. I monitor auth logs for anomalous patterns and get alerted on any successful login from an unrecognised IP.
File integrity monitoring — I deploy monitoring that tracks changes to critical system files, web server configurations, WordPress core files, and plugin directories. Any modification outside of a known maintenance window triggers an immediate alert. This catches both compromises and accidental changes before they cause damage.
Web Application Firewall (WAF) rules — I configure server-level or application-level WAF rules to block common attack patterns: SQL injection attempts, cross-site scripting payloads, directory traversal, and known vulnerability exploit signatures. ModSecurity with the OWASP Core Rule Set where applicable, or Cloudflare WAF for sites using their CDN.
Automated security updates for the operating system. Critical kernel patches, OpenSSL updates, and library security fixes are applied automatically. The server shouldn't be waiting days or weeks for a human to apply a patch for a known remote code execution vulnerability. For full server management, I cover the complete infrastructure stack — see my server management service.
Despite best efforts, breaches happen. When they do, speed and thoroughness matter more than anything else. I've handled incidents ranging from simple defacements to deeply embedded server-level compromises, and the approach is always the same: contain, investigate, remediate, harden.
The most complex incident I've resolved involved a Linux server compromised with a cryptominer. The initial symptom was straightforward — 400% CPU usage — but what I found underneath was anything but.
The attacker had deployed 14 separate persistence mechanisms to ensure the miner survived cleanup attempts: cron jobs in /etc/cron.d/, systemd services, init.d scripts, immutable file attributes set with chattr, a backdoor user account, and a remote update mechanism that re-downloaded the miner from a command-and-control server. The miner binaries were hidden in directories designed to look legitimate — /media/yum-zig/, /usr/bin/snap-bubblewrap. Even the process listing tools had been compromised to hide the mining processes from ps and top.
I've documented the full investigation and cleanup in my cryptominer cleanup blog post. That incident took several hours to fully remediate because each persistence mechanism had to be discovered and removed individually — miss one, and the miner would be back within minutes.
In another incident, I discovered an unauthorised admin user created on a CloudPanel server via the clpctl user:add command. The attacker had gained access through a web-facing vulnerability and escalated privileges to create a full admin account. I traced the attack through auth.log and sudo logs, identified base64-encoded commands in the log trail, searched the server for webshells, and removed the unauthorized access. The full investigation is detailed in my CloudPanel hack blog post.
When I respond to a security incident, I follow a structured process:
Cleaning up after a breach is only half the job. Understanding how it happened and preventing it from happening again is what separates a proper response from a temporary fix.
After every incident, I conduct a root cause analysis and implement targeted hardening:
Access review — every user account, API key, and integration credential is rotated. Any account that isn't actively needed is removed. SSH keys are regenerated. Database passwords are changed. Third-party service tokens are revoked and reissued.
Vulnerability patching — the specific vulnerability that enabled the breach is patched, along with any similar weaknesses discovered during the investigation. If a plugin was the entry point, it's either updated, replaced with a more secure alternative, or removed entirely.
Architecture improvements — sometimes an incident reveals a structural weakness. A server running multiple client sites without isolation. A WordPress installation with write permissions on files it should never modify. A database user with GRANT ALL privileges when it only needs SELECT, INSERT, UPDATE, and DELETE. These get fixed properly, not just patched.
Monitoring enhancement — I add monitoring for the specific indicators of compromise I found during the incident. If the attacker used a particular technique, I set up detection for that technique going forward. Each incident makes the monitoring more comprehensive.
Security is not a one-time setup. It's a continuous process of monitoring, alerting, and responding.
Daily malware scans — automated scanning of all WordPress files against known malware signatures, plus heuristic detection for obfuscated code patterns (eval, base64_decode, str_rot13, gzinflate). Any detection triggers an immediate alert and investigation.
Vulnerability monitoring — I track the WPScan vulnerability database and plugin/theme advisory feeds. When a vulnerability is disclosed that affects a plugin running on one of my maintained sites, I assess the risk and apply patches or mitigations before it's actively exploited.
Login monitoring — all admin login events are logged and monitored. Logins from new IP addresses, unusual times, or geographically unexpected locations are flagged for review. Failed login attempts above threshold trigger lockouts and alerts.
Uptime and availability monitoring — every site is checked every 60 seconds. Unexpected downtime can be an indicator of compromise (defacement, ransomware, resource exhaustion from cryptomining), so uptime monitoring is part of the security picture, not separate from it.
Server-level alerting — auth log monitoring for SSH brute force attempts, successful logins from unexpected sources, sudo command execution, and user account changes. These are the early warning signs that something is happening at the server level before it reaches WordPress.
WordPress security isn't a plugin you install. It's a practice — ongoing, layered, and built on experience with real incidents. My maintenance plans include security monitoring, hardening, and incident response as standard. If you've already been compromised, get in touch for emergency cleanup and recovery.
I manage 70+ WordPress sites for UK agencies and businesses. Whether you need ongoing maintenance, emergency support, or a one-off performance fix — I can help.
View Maintenance Plans Get in Touch