Guide · Hacked WHM/cPanel server

Hacked WHM or cPanel server: what to do before cleaning any site

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 covers how to tell an account compromise from a reseller or root compromise, the cPanel logs and commands to read first, and the order that contains it.

Symptom
One or more accounts flagged, outbound spam, unknown cron or processes, load spikes
First question
One cPanel account, a reseller, or root?
First step
Preserve evidence and contain the account before deleting anything
Risk
Server-wide reinfection, blacklisting of the shared IP, silent data theft

What is happening

How a cPanel account compromise spreads beyond the site

On a WHM/cPanel, Plesk, or DirectAdmin 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.

Triage

Is it one cPanel account, a reseller, or root? How to tell

The scope of the compromise decides the response. Work out which level the attacker reached before choosing between cleaning one account and rebuilding the host.

cPanel account compromised: what changes

Most incidents stop here, and the account is still the right unit of work — but only after the sweep shows the other accounts are clean. An account compromise on a server without enforced isolation is a server finding until proven otherwise.

Reseller account hacked: what changes

A reseller can suspend, modify, and in many configurations reset passwords for the accounts it owns. Assume any account under that reseller could have been changed, and check WHM’s logs for actions taken as the reseller rather than only for malware in files.

WHM root compromised: what changes

Root can edit logs, replace binaries, and hide processes, so evidence gathered on the host is no longer fully trustworthy. Collect what you can for the record, but plan the recovery as a rebuild, not a cleanup.

LevelIndicatorsWhat it meansResponse
One cPanel accountUnexpected files, cron entries, SSH keys, or processes under a single /home/USER; the account’s own logins or API tokens you cannot explain; nothing similar in other accountsThe attacker runs code as one Linux user. Isolation decides whether that user could read or write anywhere else.Contain and rotate that account, sweep every other account to confirm the boundary held, then rebuild the site
A resellerSeveral accounts owned by the same reseller affected at once; WHM logins by the reseller from unknown addresses; accounts created, modified, or given new packages without a requestThe attacker holds the reseller’s WHM credentials or a token, and can act on every account that reseller owns.Rotate the reseller’s password, 2FA and API tokens; treat every account it owns as in scope; review what the reseller changed
RootUnknown keys in /root/.ssh/authorized_keys; WHM root sessions from unfamiliar IPs; new root API tokens; changed packages, systemd units or timers; files in /root, /usr/local/bin or /etc you cannot account forEvery account, every log, and every tool on the host may have been altered — including the ones you would use to investigate.Preserve what you can, then rebuild onto a fresh host and restore accounts from verified-clean sources

Signs it is the server

Signs the server is compromised, not just one site

SignWhat it usually points toHow to check
Several accounts flagged at onceShared access, a shared vulnerability, or lateral movement — not a coincidenceList which accounts are affected and who owns them: whmapi1 listaccts want=user,owner
Outbound spam or a blacklisted IPSomething on the host is sending, whether or not any site looks infectedexim -bpc for the queue size, then the Exim checks in the spam section below
Cron entries or processes nobody recognisesScheduled persistence or a running tool owned by a hosting usercrontab -l -u USER for each account; ps -eo user,pid,etime,args --sort=user
Load, disk, or bandwidth anomaliesCryptominers, proxy nodes, or scanners running as an account userss -tnp for established outbound sessions and the process that owns each one
ImunifyAV keeps flagging the same filesA generator or scheduled task recreating what is quarantinedCompare detection times with the account’s crontab and access logs
Reinfection after a rebuildPersistence in the account, in a neighbour, or in stolen credentialsCheck SSH keys and API tokens before rebuilding again

First response

What to do first: preserve, contain, rotate, sweep

  1. 01

    Preserve before you touch

    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 the system, mail, web and cPanel logs listed in the next section. Record timestamps, owners, and hashes of anything suspicious before it is deleted or quarantined.

  2. 02

    Decide the level

    Use the account, reseller or root indicators above. If root is in doubt, stop treating the host as a trustworthy investigation tool and plan for a rebuild.

  3. 03

    Contain the account

    Suspend the cPanel account or put the site in maintenance mode, block outbound connections for that user in the firewall, kill processes owned by the user after recording them, and disable the user’s cron. Do not delete files yet.

  4. 04

    Treat the account user as compromised

    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.

  5. 05

    Sweep every account home, not just the flagged one

    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.

  6. 06

    Check the server itself

    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 the malware scanner are actually enabled and enforcing.

  7. 07

    Rebuild the application layer

    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.

  8. 08

    Close the enabling condition and verify

    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.

Evidence

cPanel logs and commands to check first

Every command below only reads. Run them as root from a trusted session and save the output outside every account home. Paths are cPanel defaults on the RHEL family (AlmaLinux, CloudLinux, Rocky); verify them against your cPanel version and distribution.

WhatWhereRead-only check
cPanel and WHM logins/usr/local/cpanel/logs/login_log and session_loggrep USER /usr/local/cpanel/logs/session_log | tail -n 50 — new sessions with their source IP
Panel requests/usr/local/cpanel/logs/access_loggrep for the account name or a suspicious IP to see what was done through cPanel, WHM, or the API
Account changes made in WHM/var/cpanel/accounting.logtail -n 100 /var/cpanel/accounting.log — account creation, removal, and changes, with who made them
SSH access/var/log/securegrep 'Accepted' /var/log/secure* — successful logins and whether they used a password or a key
Outgoing mail/var/log/exim_mainlogexim -bpc for the queue; the cwd= and A=dovecot_ checks in the spam section below
Web requests per domain/var/log/apache2/domlogs/ls -lt /var/log/apache2/domlogs/ | head, then POST requests to unexpected PHP files in the affected domain’s log
Scheduled tasks/var/spool/cron/ and /etc/cron.d/crontab -l -u USER for each account; ls -la --time-style=full-iso /var/spool/cron
Processes and connectionsLive systemps -eo user,pid,ppid,etime,args --sort=user and ss -tnp
Account isolationCloudLinux CageFScagefsctl --list-enabled — which users are actually inside CageFS
Firewall and login failuresCSF and LFD, /var/log/lfd.logcsf -g IP to see whether and why an address is allowed or blocked
Malware detectionsImunify360 or ImunifyAVimunify360-agent malware malicious list (Imunify360) or imunify-antivirus malware malicious list (ImunifyAV)
API tokensWHM and each cPanel accountwhmapi1 api_token_list for WHM; uapi --user=USER Tokens list for an account
Resellers and ownershipWHMwhmapi1 listresellers and whmapi1 listaccts want=user,owner

Where to look

Where to look on a hacked cPanel account: home, cron, SSH keys, processes

Table of six locations on a cPanel server — hidden directories in the account home, user crontabs, authorized_keys and API tokens, processes and outbound connections, world-writable temporary paths, and neighbouring accounts — none of which a WordPress security plugin reads.
Figure 1 · Outside every per-site scan

Each of these needs a root-level check; a WordPress plugin runs inside one document root and reads none of them.

Hidden directories in the account home

~/.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.

User crontabs and at jobs

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.

authorized_keys and API tokens

An SSH key or a cPanel/WHM API token survives every password rotation and every file cleanup unless it is explicitly removed.

Processes and outbound connections

A process owned by a hosting user that holds an outbound connection to an unfamiliar host — tunnels, miners, and proxies all look like this.

World-writable and temp locations

/tmp, /dev/shm, and any world-writable path are staging areas. Files there with execute bits or recent timestamps deserve attention.

Neighbouring accounts

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.

Outbound spam

Server sending spam: finding the account behind it

A blacklisted server IP is a server symptom even when every site looks clean. Before requesting delisting, establish which of three sources is sending: a mailbox whose password was stolen, a PHP mailer planted in an account, or a legitimate form being abused. The Exim main log answers that in most cases, read-only. exim -bpc counts the queue; grep -o 'cwd=[^ ]*' /var/log/exim_mainlog | sort | uniq -c | sort -rn | head lists the directories scripts sent mail from; grep -o 'A=dovecot_[a-z]*:[^ ]*' /var/log/exim_mainlog | sort | uniq -c | sort -rn | head lists the mailboxes that authenticated to send. Verify the paths against your cPanel version.

Read a sample message’s headers with exim -Mvh before deleting anything, and suspend or hold outgoing email for the one account rather than stopping mail for the whole server while you work. WHM’s Mail Delivery Reports and View Mail Statistics Summary give the same picture through the interface.

Server scanners

cxs, ImunifyAV, Maldet and CSF: what each one actually checks

These tools are often treated as interchangeable. They are not, and none of them is a root review. Editions and features change; check what your installed version does.

ToolScans filesWatches uploads or changesLooks at processes or /tmpCost
ImunifyAV / ImunifyAV+Yes — account files, on schedule or on demandReal-time scanning and Proactive Defense are Imunify360 featuresNoImunifyAV free; AV+ and Imunify360 paid
cxs (ConfigServer eXploit Scanner)YesCan hook web and FTP uploads, and watch directoriesNoCommercial licence
Maldet (Linux Malware Detect)YesOptional inotify monitoring of chosen pathsNoFree, open source
CSF and LFDNo — a firewall and login-failure daemonCan alert on suspicious files in watched directories such as /tmpCan alert on user processes and resource useFree

Other control panels

Plesk and DirectAdmin equivalents

The response is the same on every panel; only the locations change. Defaults shown — verify them on your installation.

WhatcPanel/WHMPleskDirectAdmin
Site files/home/USER/public_html/var/www/vhosts/DOMAIN/httpdocs/home/USER/domains/DOMAIN/public_html
Web logs/var/log/apache2/domlogs//var/www/vhosts/system/DOMAIN/logs//var/log/httpd/domains/
Panel logs/usr/local/cpanel/logs//var/log/plesk/panel.log and the Action Log/var/log/directadmin/
Accounts and ownerswhmapi1 listacctsplesk bin subscription --list/usr/local/directadmin/data/users/
Mail log/var/log/exim_mainlog/var/log/maillog (Postfix)/var/log/exim/mainlog
Cron per accountcrontab -l -u USERcrontab -l -u SYSTEM_USERcrontab -l -u USER

For agencies and resellers

Telling client accounts what happened

When the server hosts other people’s sites, the incident has a communication side as well as a technical one. Each account owner needs to know whether their account was in scope, what was done to it, and what they must change themselves — before they hear about a blacklist or a suspension from someone else.

  • Tell each owner whether their account was affected, merely in scope, or cleared by the sweep — with the date the sweep ran.
  • Say which credentials you rotated on their behalf, and which only they can rotate: registrar, email, payment gateways, and anything stored outside the server.
  • Give them the window during which their data was exposed if it is known, and say plainly when it is not.
  • Avoid “only one site was affected” until every account has been swept. It is the sentence most often withdrawn later.
  • Keep a written record per account of what was found, what was changed, and what remains open — the same record an insurer or a client’s security team will ask for.

After the incident

How to secure a WHM/cPanel server after a compromise

  • File-integrity monitoring above the web root, covering account homes and cron, not just public_html.
  • Execution restrictions on home directories and temp paths; CageFS or equivalent isolation enforced for every account.
  • Outbound (egress) monitoring or restriction, so a tunnel or miner cannot phone home unnoticed.
  • Two-factor authentication, cPHulk brute-force protection, and IP restriction on WHM root and reseller logins; periodic review of API tokens and SSH keys.
  • WHM’s Security Advisor run after every significant change, with each warning either resolved or recorded as an accepted exception.
  • Heuristic ELF and binary detection left enabled in the malware scanner, with alerts routed to someone who acts on them.
  • A periodic root-level review of the server, independent of per-site scans — the layer this whole guide is about.

Common questions

Common questions about hacked WHM and cPanel servers

How do I know if my cPanel account has been hacked?

Look for what the account did, not only for malware in its files: logins in the cPanel session log from addresses you do not recognise, cron entries you did not create, SSH keys or API tokens you did not add, unexpected files outside public_html, and outgoing mail you did not send. Any one of these on an account you administer is enough to treat it as compromised.

Is a hacked cPanel account the same as a hacked server?

No. A hacked account means an attacker runs code as one Linux user; a hacked server means they reached root or a reseller. The difference is whether isolation held. Until every other account has been swept and the root indicators checked, treat it as an open question rather than assuming the smaller answer.

Should I suspend the cPanel account or take the whole server offline?

Usually suspend the account and block its outbound connections, which stops harm without stopping every other customer. Take the server offline, or plan an immediate rebuild, when root compromise is likely: unknown root keys, unexplained WHM root sessions, or changed system binaries and services.

Which cPanel log files show how the attacker got in?

Start with /usr/local/cpanel/logs/session_log and login_log for panel logins, /usr/local/cpanel/logs/access_log for what was done through cPanel and WHM, /var/log/secure for SSH, the domain logs under /var/log/apache2/domlogs/ for web requests to the site, and /var/cpanel/accounting.log for account changes. On shared hosting the entry point is often older than the retained logs, so copy them before they rotate.

Does CageFS stop one account from infecting another?

It limits what an account can see of the filesystem and other users, which blocks many cross-account paths — when it is enabled for that account. Check with cagefsctl --list-enabled rather than assuming. CageFS does not protect against stolen credentials, a compromised reseller, or root.

Is cxs or ImunifyAV better for a cPanel server?

They overlap on file scanning and differ in how they are licensed, how they watch uploads, and how they clean. Either is better than none, and neither replaces a root review: neither examines SSH keys, API tokens, reseller actions, or whether isolation holds.

The server IP is blacklisted for spam. How do I find which account is sending?

Read the Exim main log. Counting the cwd= values shows which account directories handed mail to Exim, and counting A=dovecot_ entries shows which mailboxes authenticated to send. Close the source first; delisting before that only buys a few hours.

Can a compromised reseller account reach the other resellers’ accounts?

Not through WHM itself: a reseller acts on the accounts it owns. It can still reach further if the server’s isolation is weak, if credentials are reused across resellers, or if the attacker escalates to root from one of its accounts. Sweep beyond the reseller’s own accounts before concluding.

My host says only one account is infected. Can I just clean that one?

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.

Wordfence and ImunifyAV are both clean now. Is the server clean?

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.

Should I reinstall the whole server?

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.

Can you do this for a server I manage for clients?

Yes. Agencies and resellers are the most common case. The work is scoped as a server incident with per-account findings, ownership of client communication and per-site cleanup is agreed up front, and the report separates server findings from per-account actions.