secure-os.org
All guidesQubes OSTailsWhonixHardened LinuxDisk encryptionThreat model
linux

How to Check if a Linux Server Is Compromised: the Order Matters More Than the Commands

secure-os· Updated September 5, 2026· 5 min read #linux#forensics#incident-response#hardening
A row of tower servers photographed at an angle, the nearest one lit deep red with a perforated front panel and small indicator lights, the ones behind it fading into cold blue against a dark blurred background

There is a checklist for this on every sysadmin blog, and they all list roughly the same commands: ps, netstat, last, find / -mtime. The commands are fine. The problem is that they are usually presented in the wrong order, and the order is the part that decides whether the answer means anything.

If a machine has been rooted properly, the tools you are about to run are the tools the attacker had the most reason to tamper with. Running ps on a box with a kernel module hiding processes gives you a clean, reassuring, entirely false answer.

Step zero, and it is not a command

Decide first whether you are investigating or recovering. They pull in opposite directions.

Investigating means the machine stays exactly as it is: no reboot, no package updates, no cleanup. A reboot destroys the process table, the network state, and anything living only in memory, which on a modern intrusion can be most of it.

Recovering means the machine goes offline now and gets rebuilt from a known source. That is the right call more often than people admit, but it ends the investigation.

You cannot do both on the same box. Every hour spent poking at a live compromised host is an hour the attacker may still be using it.

If the machine matters, the honest sequence is: snapshot the disk, capture memory if you have the tooling, then take it off the network.

Look from outside the machine first

This is the step the checklists skip, and it is the only one an attacker on that host cannot manipulate.

Network flows from your router, hypervisor, or cloud provider. If the box is talking to an address it has no business talking to, or moving a volume of data it has never moved before, you learn that without asking the box anything. A compromised host lies about itself. Your switch does not.

The same applies to a disk snapshot. Mounting the filesystem read only from a different, trusted machine turns every subsequent check into a real one. A rootkit that hides files from ls on the running system hides nothing from another kernel reading the same blocks.

A directory listing of a Linux root filesystem shown on a black terminal in green and blue monospaced text, angled across the frame, with entries such as bin arrow usr slash bin, boot, dev, etc, home, lib arrow usr slash lib, lost and found, private arrow slash home slash encrypted, proc, root, sbin and var, each preceded by a size and a September 2015 timestamp

What to actually look at, in descending order of usefulness

Accounts and authentication. Read /etc/passwd and /etc/shadow for accounts you did not create, especially any with UID 0 other than root. Check ~/.ssh/authorized_keys for every user that has a home directory, root included. An added public key is the most common persistence mechanism there is, because it survives password changes and it looks like configuration.

Scheduled work. crontab -l for each user, plus /etc/cron.*, plus systemd timers via systemctl list-timers --all. Timers are checked far less often than cron and they do the same job.

Services that start themselves. systemctl list-unit-files --state=enabled and then look for unit files whose names you do not recognise, or whose ExecStart points somewhere writable like /tmp, /dev/shm, or a user home directory.

Listening sockets. ss -tulpn rather than the deprecated netstat. You are looking for a listener you cannot account for, and for a process name that does not match the port.

Package integrity. On Debian and Ubuntu, debsums -c lists files that no longer match what the package manager installed. On RHEL family systems, rpm -Va. This is genuinely useful and almost nobody runs it. It is also worth knowing its limit: it validates files that came from packages, so anything dropped outside a package is invisible to it.

Recently modified files. find / -xdev -mtime -7 -type f gives you the last week of changes. Expect noise from logs and caches. Look for changes in /bin, /sbin, /usr/bin, /lib, and for anything executable in /tmp or /dev/shm.

The log question, answered honestly

Everyone says read the logs. The useful version is narrower: read the logs you shipped somewhere else.

Logs on the compromised machine tell you what the attacker chose to leave. /var/log/auth.log or /var/log/secure may show the successful login that started this, or it may show a clean file with a suspicious gap. A gap is itself a finding. So is a wtmp that last reads without complaint but whose size does not match its history.

If you are running fail2ban or shipping logs to a separate host, that external copy is worth more than everything on the local disk.

The one conclusion you are allowed to draw

If you find a rootkit, you know the machine is compromised. If you find nothing, you have not learned that the machine is clean. You have learned that the checks you ran did not detect anything, which is a much smaller statement.

Tools like rkhunter and chkrootkit are worth running for the same reason and with the same caveat: they match known signatures, on a system that may be lying to them.

This is why the rebuild option keeps coming back. A machine you rebuild from source, with keys rotated and credentials replaced, is in a state you can reason about. A machine that passed a checklist is in a state you hope about.

What to do before you need this

Three things make the difference between a two hour answer and a two day one, and all three have to exist before the incident:

  • Logs shipped off the machine, so there is a copy the attacker never touched.
  • A file integrity baseline, from AIDE, Tripwire, or even a stored hash list. Comparing against a known good state is a different activity from guessing.
  • Snapshots you can actually mount, which is what turns the trusted-machine method above from a good idea into a fifteen minute job.

If you are hardening a server rather than investigating one, the groundwork is covered in our Linux hardening guide, and process isolation is covered in Linux sandboxing.