Is my Linux server hacked? A step-by-step check
A practical runbook for the worst feeling in ops: something's off and you don't know why. Check sessions, processes, network, persistence, and file changes in order - with the exact commands - and know what to do if you find something.
Sandeep Sidhu · Founder, AlertKick
To check whether a Linux server is hacked, run five checks in this order: w and last -a for live and recent sessions, ps auxwwf for suspicious processes, ss -tupan for unexplained network connections, then cron, systemd units, and authorized_keys for persistence, and finally package verification (debsums or rpm -Va) for modified binaries. Each takes a minute, and every command is pasteable below.
If you’re here, the server probably feels wrong. Load is up for no reason, an IP you don’t recognise is in the logs, outbound traffic looks odd, or you just have that prickle of doubt. Work through the list in order - it goes from “who is here right now” to “what have they left behind”.
One rule first: look, don’t clean - yet. If the box really is compromised, your instinct to delete the weird file destroys the evidence that tells you how they got in. Read first, snapshot what you find, then act.
1. Who is on the box right now?
w # live sessions: user, source IP, what they're running
last -a | head -20 # recent logins, newest first, source host in last column
lastb -a | head -20 # recent FAILED logins (needs root) - brute-force evidence
Red flags: users you don’t recognise, logins from unfamiliar IPs or countries, sessions at hours nobody on the team works, or a last entry for a system account (www-data, postgres) that should never log in interactively.
2. What is running?
ps auxwwf # full process tree - read it, slowly
top -o %CPU # anything pinning CPU you can't explain?
ls -la /proc/<pid>/exe # where a suspicious process actually runs from
cat /proc/<pid>/cmdline | tr '\0' ' '
Red flags: processes running from /tmp, /dev/shm, or a user’s home directory. Names that mimic system processes (kworkerd, systemd-net - note the slight misspellings). Anything with a random-looking name pinning a core. A deleted binary still running shows as (deleted) on the /proc/<pid>/exe symlink. That is a classic miner trick and a very strong signal.
3. Who is the box talking to?
ss -tupan | grep -v 127.0.0.1 # all sockets, with owning process
ss -tlpn # listening ports - do you recognise every one?
Red flags: established outbound connections to unattributed IPs (miner pools and C2 servers live here), listening ports you didn’t configure, or a familiar service on an unfamiliar port. Check suspicious remote IPs against a threat-intel source before dismissing them.
4. What survives a reboot?
Attackers assume you’ll reboot; persistence is where they invest. Check every launcher:
crontab -l; ls -la /etc/cron.* /var/spool/cron 2>/dev/null
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled | grep -v static
cat ~/.ssh/authorized_keys /root/.ssh/authorized_keys 2>/dev/null
grep -r "curl\|wget" /etc/rc.local /etc/profile.d/ 2>/dev/null
Red flags: cron entries that curl or wget anything, systemd services you didn’t install, and SSH keys in authorized_keys that you didn’t put there. An added key is the single most common persistence mechanism, because it survives password rotation.
5. What changed on disk?
find /etc /usr/bin /usr/sbin -mtime -7 -type f 2>/dev/null | head -40
debsums -c 2>/dev/null # Debian/Ubuntu: verify package file checksums
rpm -Va 2>/dev/null | head -40 # RHEL/Fedora equivalent
Red flags: recently modified binaries in system paths, config files changed when nobody deployed, or checksum failures on packaged files. Add chkrootkit or rkhunter for a rootkit sweep. The tools are imperfect but cheap to run.
If you found something
- Don’t power off. Memory is evidence. Isolate instead: tighten the firewall to your own IP, or detach the box from the network at the provider level.
- Snapshot first - disk snapshot at the provider, plus copies of
auth.log, shell histories, and your command output above - then remediate. - Assume credential compromise. Rotate every secret the box could see: SSH keys, API tokens, database passwords, cloud credentials in env files.
- Prefer rebuild to cleanup. If persistence was installed, a “cleaned” server is a server where you hope you found everything. Rebuild from known-good, restore data (not binaries), and close the entry hole before it goes back on the network.
The gap this checklist can’t close
Every command above answers “what is true right now?” - and the checks only run when suspicion has already arrived. The gap between compromise and that prickle of doubt is where the damage happens, and on most servers that gap is measured in weeks.
Closing it means watching continuously instead of checking retrospectively. Every step in this runbook is a detection AlertKick’s eBPF agent runs in real time - SSH logins as they happen, processes launched from /tmp, new listening ports, authorized_keys and system-file changes, connections to known-bad IPs from live threat feeds - each mapped to MITRE ATT&CK and triaged by AI so you hear about the real ones.
Start free and put the agent on the server you were worried enough about to read this far. The next time something’s off, you won’t be finding out from a feeling.
Frequently asked questions
- How do you check if a Linux server has been hacked?
- Run five checks in order: w and last -a for live and recent sessions, ps auxwwf for suspicious processes, ss -tupan for unexplained network connections, then cron, systemd units, and authorized_keys for persistence, and finally package verification with debsums or rpm -Va for modified binaries. Each takes about a minute. Look and record before cleaning anything, because deleting the weird file destroys the evidence of how they got in.
- What are the signs of a compromised Linux server?
- Logins from unfamiliar IPs or at hours nobody works, interactive sessions for system accounts like www-data or postgres, processes running from /tmp, /dev/shm, or a home directory, process names that mimic kernel threads with slight misspellings, a running process whose /proc/<pid>/exe link shows (deleted), outbound connections to IPs you cannot attribute, listening ports you did not configure, cron entries that curl or wget something, systemd services you did not install, SSH keys in authorized_keys you did not add, and recently modified binaries in system paths.
- Where do attackers hide persistence on Linux?
- In cron (crontab -l, /etc/cron.*, /var/spool/cron), enabled systemd units, /etc/rc.local and /etc/profile.d/ scripts, and above all in ~/.ssh/authorized_keys and /root/.ssh/authorized_keys. An added SSH key is the single most common persistence mechanism because it survives password rotation.
- Should you power off a hacked server?
- No. Memory is evidence, so isolate the box instead - tighten the firewall to your own IP or detach it from the network at the provider level. Take a disk snapshot at the provider plus copies of auth.log, shell histories, and your command output before remediating anything.
- Should you clean a hacked server or rebuild it?
- Prefer rebuild. If persistence was installed, a cleaned server is one where you hope you found everything. Rebuild from a known-good image, restore data but not binaries, rotate every secret the box could see (SSH keys, API tokens, database passwords, cloud credentials in env files), and close the entry hole before it goes back on the network.
- How do you find out a server is hacked before you get suspicious?
- Every manual check answers 'what is true right now' and only runs once suspicion has arrived, and on most servers the gap between compromise and that suspicion is measured in weeks. Closing it takes continuous watching: an eBPF agent that reports SSH logins as they happen, processes launched from /tmp, new listening ports, authorized_keys and system-file changes, and connections to known-bad IPs from live threat feeds, with each event mapped to MITRE ATT&CK and triaged so the real ones are what reaches you.