Several accounts flagged at once
Two or more unrelated sites on the same server showing malware, spam pages, or redirects points to shared access, a shared vulnerability, or lateral movement — not a coincidence.
Guide · Hacked WHM/cPanel server
One account on the server is flagged — by VirusTotal, a blacklist, an ImunifyAV alert, outbound spam, or a customer complaint. The instinct is to clean that site and move on. On a shared control-panel server that instinct is how the same server gets re-flagged next month: the mechanism usually lives outside the site, in the account home, cron, the process table, or a neighbouring account. This guide sets out what to do first, what to look at, and when a per-site cleanup is safe to start.
Published Last reviewed
What is happening
On a WHM/cPanel or Plesk server, each hosting account is a Linux user with a home directory, a crontab, the ability to run processes, and — unless isolation is configured carefully — a view of its neighbours. A compromised WordPress site gives an attacker code execution as that user. From there the interesting places are not in public_html at all: a hidden directory under ~/.config, a cron entry that re-downloads the payload, an SSH key in ~/.ssh/authorized_keys, a cPanel API token, or an outbound tunnel that keeps working after every file cleanup.
In the engagement documented in our incident report, Wordfence flagged 283 files on one WooCommerce shop, ImunifyAV agreed, and the database export was clean. All three were right about their own layer. The backdoor was a packed ELF binary in ~/.config/htop/defunct — outside the web root, invisible to every per-site tool, on a server hosting 261 accounts. Only a root-level filesystem review found it.
That is why the order of operations matters more than the cleanup itself. Clean the site first and you destroy timestamps, overwrite logs, and leave the mechanism in place.
Signs it is the server
Two or more unrelated sites on the same server showing malware, spam pages, or redirects points to shared access, a shared vulnerability, or lateral movement — not a coincidence.
The server’s IP on Spamhaus, SORBS, or a mail-provider block list means something on the host is sending, whether or not any site looks infected.
Entries in a user crontab that fetch a URL, run from /tmp or /dev/shm, or invoke a file with a misleading name; processes owned by a hosting account that are not PHP-FPM or a known cron job.
Cryptominers, proxy nodes, and scanning tools show up as sustained CPU, unexplained outbound traffic, or a full /tmp before any site symptom appears.
Files reappearing after quarantine means a generator or a scheduled task is recreating them — the quarantine is treating output, not cause.
A site rebuilt from clean sources that is compromised again within days almost always has persistence in the account, in a neighbour, or in stolen credentials.
First response
Take a filesystem-level snapshot or an rsync copy of the affected account’s entire home directory (not just public_html), export the crontab, and copy /var/log/messages, secure, maillog, and the Apache/Nginx and cPanel access logs for the account. Record timestamps, owners, and hashes of anything suspicious before it is deleted or quarantined.
Suspend the cPanel account or put the site in maintenance mode, block outbound connections for that user in CSF or the firewall, kill processes owned by the user after recording them, and disable the user’s cron. Do not delete files yet.
Rotate the cPanel password, FTP/SFTP accounts, database passwords, API tokens, and any SSH keys in the account. Check ~/.ssh/authorized_keys for keys you did not add. Assume every credential stored in the account’s wp-config.php and .env files has been read.
For each user: list hidden directories and recently modified files outside public_html, look for executables where none belong, check crontabs, and compare against a known-good baseline. On a multi-account server this is the step that decides whether the incident is over.
Root and reseller WHM logins and access logs, WHM API tokens, root’s authorized_keys, systemd timers, /tmp and /dev/shm contents, listening and outbound connections, and whether CageFS, PHP handler isolation, and ImunifyAV are actually enabled and enforcing.
Only now rebuild WordPress core, plugins, and themes from trusted sources, clean the database, and rotate WordPress credentials — following the same discipline as any hacked-site cleanup.
Patch or remove the vulnerable component, fix the isolation gap, and re-check the server after normal traffic resumes: cron, processes, outbound connections, and file changes over the following days.
Where to look
~/.config, ~/.cache, ~/.local, and dot-directories with names that imitate legitimate tools. Executables or packed binaries here are the artefact class from our incident report — see the gsocket guide for the exact paths to check.
Entries that curl or wget a URL, execute from /tmp, or run a script with a system-looking name every few minutes are the most common persistence on cPanel servers.
An SSH key or a cPanel/WHM API token survives every password rotation and every file cleanup unless it is explicitly removed.
A process owned by a hosting user that holds an outbound connection to an unfamiliar host — tunnels, miners, and proxies all look like this.
/tmp, /dev/shm, and any world-writable path are staging areas. Files there with execute bits or recent timestamps deserve attention.
If isolation is weak, the flagged account may be the victim of a neighbour, or the neighbour may already be the next victim. The sweep has to cover the server.
After the incident
Common questions
You can clean it, but you cannot conclude the incident is over from that statement alone. Ask the host what they checked: a per-account malware scan does not cover cron, processes, hidden home-directory files, or neighbouring accounts. If you administer the server, sweep it yourself or have it reviewed at root level.
They are clean about their own layers — WordPress files and the files ImunifyAV is configured to scan. Neither examines the process table, user crontabs, SSH keys, API tokens, or a packed binary in a hidden dot-directory. The documented WHM incident is exactly this case.
Sometimes. If root access is suspected, if isolation was never configured, or if the number of accounts makes a reliable sweep impractical, a rebuild onto a fresh host with accounts restored from verified-clean application sources is the safer path. A contained single-account compromise with intact root controls usually does not need it.
Yes. Agencies and resellers are the most common case. The work is scoped as a server audit with incident handling, ownership of client communication and per-site cleanup is agreed up front, and the report separates server findings from per-account actions.