Incident Response ยท Last verified 2026-05-17

How to Find Hidden Backdoors on Your Linux Server After a Hack

You patched the vulnerability. You rotated the root password. You feel better. You shouldn't. Attackers who get root on a Linux box can plant persistence within seconds, and much of it survives a reboot, a password change, and even a full cPanel update cycle. Check the re-entry paths before you call the server clean.

Don't reboot first

A lot of backdoors live partly in memory, and reboots wipe them along with the evidence you'd use to prove they were ever there. Work from a live system whenever possible. Take a disk snapshot through your hosting provider's panel before you touch anything. If your provider is Hetzner, DigitalOcean, Vultr, or Linode, there's a one-click snapshot button. Use it.

Step 1: SSH authorized_keys

This is the single most common persistence mechanism we see. It takes one line to add, it survives password resets, and most admins don't check it because they assume SSH keys are "their" keys. Run this:

cat /root/.ssh/authorized_keys

If there's a key you don't recognize, remove it. Don't second-guess yourself. If you didn't put it there, it doesn't belong. Then check every user on the box:

for user in $(cut -d: -f1 /etc/passwd); do
  keyfile="/home/$user/.ssh/authorized_keys"
  [ -f "$keyfile" ] && echo "=== $user ===" && cat "$keyfile"
done

Pay special attention to system accounts that shouldn't have keys at all. In the CVE-2026-41940 campaign, attackers added keys to root, nobody, and sometimes to a freshly created user named pakchoi or a random 8-character string.

Step 2: Cron jobs

Cron is the second-favorite persistence spot because it's reliable, quiet, and admins rarely audit it. You need to check all of these locations:

crontab -l
ls -la /etc/cron.d/
ls -la /etc/cron.hourly/ /etc/cron.daily/ /etc/cron.weekly/ /etc/cron.monthly/
cat /etc/crontab
ls -la /var/spool/cron/

Look at modification timestamps. If any file in /etc/cron.d/ was modified after the compromise date, open it and read every line. The patterns I see most often: curl or wget piped into bash, base64-encoded payloads, and reverse-shell one-liners disguised as maintenance scripts. One campaign we tracked disguised the cron entry as cpanel_daily_backup.sh. Looked legitimate at a glance. Wasn't.

Don't forget /etc/anacrontab. It is less common, which is exactly why attackers sometimes hide persistence there.

Step 3: Systemd units

Modern attackers increasingly drop custom .service files. Systemd persistence is cleaner than cron, restarts automatically if killed, and blends in with the hundreds of legitimate units already on the box.

systemctl list-units --type=service --state=running | grep -v -E '(systemd|cron|ssh|rsyslog|cpanel)'

Anything that looks unfamiliar, inspect it:

systemctl cat suspicious-service-name

Check these directories for recently created .service files:

find /etc/systemd/system/ /usr/lib/systemd/system/ -name '*.service' -newer /etc/passwd -ls

The -newer /etc/passwd trick filters for files created after the last user change. It's not foolproof, but it catches most drop-ins. Also check for .timer units. Systemd timers are the modern equivalent of cron, and some attackers prefer them.

Step 4: Hidden users and sudo access

Check for users added to privileged groups:

getent group sudo
getent group wheel
grep ':0:' /etc/passwd

That last command looks for users with UID 0 (root-equivalent). You should see exactly one line: root. If there's a second entry, treat it as a likely backdoor. In the cPanel campaign, public reports described attackers creating users with GID 0 (the pakchoi user mentioned in several Reddit reports had root-level group privileges).

Then check sudoers:

cat /etc/sudoers
ls -la /etc/sudoers.d/

Any entry granting NOPASSWD: ALL to a user you didn't create is a confirmed backdoor. Remove it immediately.

Step 5: Web shells

Web shells are the most common persistence for WordPress and cPanel environments because they're accessible from the internet without SSH. The standard approach:

find /home/*/public_html/ -name '*.php' -newer /etc/passwd -size +0 -size -500k \
  -exec grep -l -E '(eval|base64_decode|system|passthru|shell_exec|assert)' {'{}'}  \;

This finds PHP files modified after the compromise that contain common shell functions. It'll produce false positives from legitimate plugins, so you'll need to eyeball the results. Focus on files in unexpected locations: a wp-includes/class-wp-session.php that WordPress didn't ship, a .cache.php in the document root, or anything in wp-content/uploads/ with a .php extension.

For non-PHP stacks, adjust the extensions. Python web shells can be dropped as .py files in CGI directories, and Go binaries (like the Mr_Rot13 Filemanager backdoor) placed in /usr/local/bin/ or /tmp/.

Step 6: Network connections

Check what's talking to the outside world right now:

ss -tulnp

Look for processes listening on unexpected ports. The Mr_Rot13 Filemanager backdoor binds its bcrypt-protected web GUI somewhere in the 8000-9999 port range. Cryptominers often listen on high ports for pool connections. Any ESTABLISHED connection to an IP you don't recognize warrants investigation.

ss -tnp state established | awk '{'{'}print $5{'}'}' | sort -u

Cross-reference unknown IPs against threat intelligence. The Mr_Rot13 C2 domains are wrned[.]com and wpsock[.]com. If you see connections to either, your server is actively being controlled.

Step 7: Binary tampering and LD_PRELOAD

Sophisticated attackers replace system binaries or inject shared libraries. This is harder to detect but worth checking:

rpm -Va 2>/dev/null | grep -E '^..5'
dpkg --verify 2>/dev/null | grep -v '^..' 

The RPM command (CentOS/AlmaLinux/Rocky) flags files where the hash doesn't match the installed package. Pay attention to binaries like ps, ls, netstat, and ss. If an attacker replaces ps, you won't see their processes in process listings. That's the whole point.

Check for LD_PRELOAD hooks:

cat /etc/ld.so.preload
echo $LD_PRELOAD
find /etc/ld.so.conf.d/ -type f -exec cat {'{}'}  \;

A non-empty /etc/ld.so.preload on a server that hasn't been deliberately configured for it is a red flag. Attackers use preloaded libraries to intercept system calls and hide processes, files, or connections from standard tools.

Step 8: WHM API tokens and cPanel sessions

This one is specific to cPanel/WHM servers. Attackers who get in through CVE-2026-41940 often create API tokens as a backup re-entry path. The tokens grant root-equivalent API access and survive password resets.

ls -la /var/cpanel/session/raw/
whmapi1 listremoteaccesskey 2>/dev/null

In WHM, go to Development - Manage API Tokens. Revoke anything you didn't create. If you're unsure, revoke it anyway and recreate the ones you actually need. It takes two minutes and closes a persistence path that most people skip.

Step 9: Process tree inspection

Get a full process tree and look for anything that doesn't belong:

ps auxf --sort=-%cpu | head -50

Cryptominers are easy to spot because they peg CPU at 100%. More subtle backdoors sit idle and use almost no resources. Look for processes running from /tmp/, /dev/shm/, or /var/tmp/. Legitimate software doesn't run from temporary directories.

Check for deleted-but-running binaries:

ls -la /proc/*/exe 2>/dev/null | grep '(deleted)'

A process whose binary has been deleted from disk but is still running in memory is exactly what it sounds like: someone ran it, then removed the file to cover their tracks.

The hard truth about cleaning

If you've confirmed even one persistence mechanism, you can't trust the server anymore. You don't know what you missed. The safe path is to migrate to a clean server from backups that predate the compromise. The risky path is to try removing everything you found and hoping you got it all.

For the CVE-2026-41940 campaign specifically, multiple persistence layers have been reported: SSH keys, cron jobs, a Go binary, and web shells. Remove only part of the stack and the server can be re-entered.

If migration isn't possible (because backups are compromised too, or there are no backups), at least run through every step in this guide twice. Then run through it again in a week, because some persistence mechanisms are designed to re-deploy after removal.

Free tools that help

  • cPanel IOC checker: cPanel's official ioc_checksessions_files.sh script catches session-based compromise artifacts. Get it from cPanel's security advisory.
  • Ping7 cPanel Detector: our open-source 12-point bash scanner checks for Mr_Rot13 Filemanager, .sorry files, rogue SSH keys, cron persistence, and more. GitHub repo.
  • rkhunter / chkrootkit: the classic rootkit scanners. They won't catch everything (especially custom Go binaries), but they're a useful baseline.
  • Lynis: full security audit tool. Run lynis audit system for a complete system report.

When to call in help

If you've found the Filemanager backdoor, cryptominer processes, or .sorry-encrypted files, the compromise is deep enough that a DIY cleanup carries real risk. Ping7 can help with clean-server migration, client data preservation, and email continuity. Request CVE repair, or start with our free CVE-2026-41940 self-check guide to understand the full scope.

Sources: Nocinit post-compromise guide (2026-05-02), Censys telemetry showing 8,859 hosts with .sorry artifacts (2026-05-08), cPanel security advisory CVE-2026-41940 (2026-04-28), Shadowserver Foundation honeypot data showing 44,000 compromised IPs (2026-04-30).