Meet us at CloudFest Americas Nov 10–12 · Miami

Book a meeting
Runbook · Security

Has My Linux Server Been Hacked? A Compromise Checklist

A step-by-step checklist for spotting a compromised Linux server, covering logins, processes, network connections, cron jobs, SSH keys and modified files, and what to do if you find one.

Applies to
  • AlmaLinux
  • Rocky Linux
  • RHEL
  • Ubuntu
  • Debian
  • cPanel servers
Skill level
Advanced
Last reviewed

Quick answer: Look for unfamiliar logins (last), unknown high-CPU processes (ps), unexpected network connections (ss), new cron jobs or systemd timers, extra SSH keys or root-level users, and modified system binaries (rpm -Va or debsums). If you find evidence of a root-level compromise, don't try to clean it: isolate the server, preserve evidence, rebuild from a known-good source, and rotate every credential.

Warning signs

  • CPU pinned at 100% by a process you don't recognize, often a cryptocurrency miner
  • Your server's IP address appears on spam blocklists, or the mail queue is full of messages you didn't send
  • Your hosting provider reports outbound attacks or abuse coming from the server
  • Websites redirect visitors elsewhere, or contain links and files you didn't add
  • New user accounts, SSH keys or scheduled tasks

Treat the server's own tools with suspicion. Sophisticated attackers replace commands like ps, ls and ss with versions that hide their activity. A clean result from a compromised machine is not proof that it's clean, which is why Step 7 checks the binaries themselves.

Step 1: Who has logged in?

# Recent successful logins, with source addresses
last -a | head -30

# Who is logged in right now
w

# Successful SSH logins: RHEL family, then Ubuntu / Debian
grep "Accepted" /var/log/secure | tail -30
grep "Accepted" /var/log/auth.log | tail -30

Look for logins from countries or networks you don't use, at unusual times, or to accounts that shouldn't log in at all.

Step 2: What's running?

# Top CPU consumers, with the full process tree
ps auxf --sort=-%cpu | head -25

Be suspicious of random-looking process names, processes running from /tmp, /var/tmp or /dev/shm, and anything imitating a system name, such as kworker run by a non-root user. To see where a suspicious process's program actually lives:

ls -l /proc/PID/exe

Step 3: What's talking to the network?

# Listening ports, with the owning process
ss -tulpn

# Established connections
ss -tunp state established

Look for listeners on ports you didn't open, and outbound connections to IRC servers, mining pools, or unusual high ports.

Step 4: Scheduled tasks

Attackers make sure their code comes back after a reboot. Check every user's crontab, the system cron directories, and systemd timers:

for u in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$u" 2>/dev/null | grep -v '^#' | sed "s/^/$u: /"; done
ls -la /etc/cron.* /etc/crontab /var/spool/cron/ 2>/dev/null
systemctl list-timers --all

Step 5: Accounts and SSH keys

# Any account other than root with UID 0 is a red flag
awk -F: '$3 == 0' /etc/passwd

# Accounts that can log in
grep -v -E "nologin|false" /etc/passwd

# Every authorized_keys file, and when it last changed
find / -name authorized_keys -type f -exec ls -la {} \; 2>/dev/null

Open each authorized_keys file and make sure you recognize every key.

Step 6: Suspicious files

# Executables in world-writable temp locations
find /tmp /var/tmp /dev/shm -type f -perm -u+x 2>/dev/null

# Files changed in the last 3 days under system binary directories
find /usr/bin /usr/sbin /bin /sbin -type f -mtime -3 2>/dev/null

For websites, look for recently modified PHP files in upload directories, where they should never be:

find /var/www /home/*/public_html -name "*.php" -path "*uploads*" -mtime -14 2>/dev/null

Step 7: Verify system binaries against packages

# AlmaLinux / Rocky / RHEL: verify installed files against the package database
rpm -Va | grep -E "^..5" | grep -E " /(usr/)?s?bin/"

# Ubuntu / Debian (install debsums first)
debsums -s

In rpm -Va output, a 5 as the third character of a line means the file's checksum no longer matches the package. On a system binary like /usr/bin/ps, that strongly suggests a rootkit. (Configuration files, marked with a c, change legitimately.)

Step 8: Run a scanner for a second opinion

Tools like rkhunter and chkrootkit check for known rootkits. Web malware scanners such as ImunifyAV or Linux Malware Detect (maldet) look for infected website files. Treat their results as clues, not verdicts. False positives are common, and a clean scan doesn't prove much.

If you find a compromise

  1. Isolate the server from the network, or firewall it to your own IP address only, so it stops attacking others or leaking data.
  2. Preserve evidence: take a snapshot or disk image before changing anything, especially if customer data may be involved and you have notification obligations.
  3. Rebuild, don't clean. Once an attacker has had root access, you can't be confident you found everything. Build a fresh server, restore data from a backup taken before the compromise, and reinstall applications from trusted sources.
  4. Rotate every credential: root and user passwords, SSH keys, database passwords, API keys, and any credentials stored in application config files.
  5. Find the way in and close it, whether that's an outdated plugin, a weak password or an unpatched service, so it doesn't happen again.

Prevent it

  • Patch the operating system and applications promptly. Most compromises exploit known, already-fixed vulnerabilities. See our Linux end-of-life checklist.
  • Use SSH keys instead of passwords, and disable direct root login.
  • Run a firewall and brute-force protection.
  • Monitor CPU, outbound traffic and the mail queue, so anomalies raise an alert.

Think your server has been compromised? Contact us right away or call (800) 269-6465. We'll help you contain it, investigate and rebuild safely, then keep it secure with proactive server management.