Skip to main content

How to Detect and Respond to a Compromised Linux Server

13 min read
Investigate my Linux server

We triage the server, preserve evidence, contain the intrusion and write up the incident report.

A practical incident response guide for Linux servers: identifying signs of compromise, initial triage, evidence preservation, containment, rootkit detection, and writing an incident report.

Introduction

Discovering that a server has been compromised is one of the most stressful moments in operations. The decisions we make in the first 30 minutes determine whether we contain the incident quickly or allow the attacker to spread laterally through the network. This guide provides a structured approach to detecting, triaging, and responding to a compromised Linux server.

Recognizing the Signs

Not every anomaly means a breach, but the following indicators warrant immediate investigation:

  • Unexpected spikes in outbound network traffic
  • Unknown processes consuming CPU or memory
  • Modified system binaries (e.g., ls, ps, netstat behaving oddly)
  • New user accounts or SSH keys we did not create
  • Cron jobs we did not schedule
  • Log files that have been truncated or deleted
  • Files with recent modification timestamps in system directories
  • Connections to known-bad IP addresses

Phase 1: Initial Triage (Do Not Reboot)

The first rule of incident response is to preserve evidence. Rebooting destroys volatile data (running processes, network connections, memory contents).

1.1 Check Active Connections

# List all established connections with process names
ss -tulnp | grep ESTAB

# Look for connections to unusual ports or IPs
netstat -anp | grep ESTABLISHED

1.2 Inspect Running Processes

# Full process tree
ps auxf

# Look for processes running from /tmp, /dev/shm, or hidden directories
ls -la /tmp /dev/shm
find /tmp /dev/shm -type f -executable

# Check for processes masquerading as system services
ps aux | grep -E '\./|/tmp/|/dev/shm/'

1.3 Review Recent User Activity

# Who is currently logged in
w

# Recent logins
last -20

# Failed login attempts
lastb -20

# Check for new users
grep -v "nologin\|false" /etc/passwd

# Look for unauthorized SSH keys
find / -name "authorized_keys" -exec cat {} \;

1.4 Examine Cron Jobs

# Check all user crontabs
for user in $(cut -f1 -d: /etc/passwd); do
  echo "=== $user ==="
  crontab -l -u "$user" 2>/dev/null
done

# Check system cron directories
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/

Phase 2: Evidence Preservation

Before making any changes, capture evidence. This is critical for forensic analysis and may be required for legal proceedings.

# Create an evidence directory on an external volume
mkdir -p /mnt/evidence/$(hostname)_$(date +%Y%m%d)
EVIDENCE="/mnt/evidence/$(hostname)_$(date +%Y%m%d)"

# Dump running processes
ps auxf > "$EVIDENCE/ps_auxf.txt"

# Dump network connections
ss -tulnp > "$EVIDENCE/ss_tulnp.txt"
netstat -anp > "$EVIDENCE/netstat_anp.txt"

# Dump open files
lsof > "$EVIDENCE/lsof.txt"

# Copy auth logs
cp /var/log/auth.log "$EVIDENCE/"
cp /var/log/syslog "$EVIDENCE/"

# Dump currently loaded kernel modules
lsmod > "$EVIDENCE/lsmod.txt"

# Hash critical system binaries for later comparison
sha256sum /usr/bin/ps /usr/bin/ls /usr/bin/netstat /usr/bin/ss > "$EVIDENCE/binary_hashes.txt"

Phase 3: Containment

Once evidence is preserved, we contain the breach to prevent further damage.

3.1 Network Isolation

# Block all outbound traffic except our management IP
sudo iptables -F
sudo iptables -A INPUT -s OUR_MGMT_IP -j ACCEPT
sudo iptables -A OUTPUT -d OUR_MGMT_IP -j ACCEPT
sudo iptables -A INPUT -j DROP
sudo iptables -A OUTPUT -j DROP

3.2 Kill Malicious Processes

# Identify the PID of the suspicious process
kill -9 <PID>

# If the process respawns, check for a parent process or cron job

3.3 Revoke Compromised Credentials

# Lock user accounts
passwd -l suspicious_user

# Remove unauthorized SSH keys
# Rotate all passwords and API keys that were on this server

Phase 4: Rootkit Detection

# Install and run rkhunter
sudo apt install -y rkhunter
sudo rkhunter --update
sudo rkhunter --check --skip-keypress

# Install and run chkrootkit
sudo apt install -y chkrootkit
sudo chkrootkit

# Compare system binary hashes against a known-good baseline
debsums -c

Phase 5: Recovery

After containment and analysis, we have two options:

  1. Clean and patch the existing server (only if we are confident we have identified the full scope of the compromise).
  2. Rebuild from scratch using a clean image and restore data from a known-good backup (the recommended approach for production servers).

We strongly recommend option 2 for production systems. An attacker who gained root access may have installed persistent backdoors that are extremely difficult to detect.

Phase 6: Incident Report

Every security incident should result in a written report that includes:

  • Timeline: When the compromise occurred, when it was detected, when it was contained
  • Scope: Which systems and data were affected
  • Root cause: How the attacker gained access (unpatched vulnerability, stolen credentials, misconfiguration)
  • Evidence: Logs, process dumps, hashes
  • Remediation: What was done to contain and recover
  • Lessons learned: What we will change to prevent recurrence

Incident response is not something we want to figure out during an actual incident. We should have runbooks prepared, practice them regularly, and ensure the team knows who to contact and what steps to take. The commands in this guide form the foundation of a Linux incident response toolkit.

Frequently asked questions

What are the signs that a Linux server has been hacked?

Warning signs include unexpected spikes in outbound traffic, unknown processes eating CPU or memory, and system binaries such as ls, ps or netstat behaving oddly. New user accounts, SSH keys or cron jobs nobody created are red flags too, as are truncated or deleted logs, recently modified files in system directories and connections to known-bad IP addresses. Any one of these warrants immediate investigation, even though not every anomaly means a breach.

Should I reboot a compromised Linux server?

No. Rebooting a compromised Linux server destroys volatile evidence such as running processes, network connections and memory contents. Triage the live system first with ss -tulnp, ps auxf, w, last -20 and a review of every crontab, and save that output to an external volume before changing anything. Decisions made in the first 30 minutes determine whether the incident is contained quickly or the attacker spreads laterally.

How do I preserve evidence on a hacked Linux server?

Create a dated evidence directory on an external volume, such as /mnt/evidence with the hostname and date in the folder name, and write every capture there. Save the output of ps auxf, ss -tulnp, netstat -anp, lsof and lsmod, copy /var/log/auth.log and /var/log/syslog, and record sha256sum hashes of /usr/bin/ps, /usr/bin/ls, /usr/bin/netstat and /usr/bin/ss. Do all of it before making changes, because the evidence feeds forensic analysis and may be needed in legal proceedings.

How do I isolate a compromised Linux server from the network?

Once evidence is saved, flush the firewall with iptables -F, accept input from and output to one management IP, then add DROP rules for all other INPUT and OUTPUT traffic. The admin connection stays open while everything else is cut off. Kill malicious processes with kill -9, and if one respawns, look for a parent process or cron job that keeps restarting it.

Which tools detect rootkits on a Linux server?

Two rootkit scanners for Linux are rkhunter and chkrootkit, both installed through apt. Update rkhunter with sudo rkhunter --update, run sudo rkhunter --check --skip-keypress, then run sudo chkrootkit. On top of that, debsums -c compares system binary hashes against a known-good baseline, which helps reveal modified binaries.

Should I clean or rebuild a compromised Linux server?

Rebuilding from a clean image and restoring data from a known-good backup is the recommended path for production servers. Cleaning and patching the existing machine is only reasonable when the full scope of the compromise has been identified with confidence. An attacker who gained root may have installed persistent backdoors that are extremely difficult to detect.

What should a server security incident report include?

A security incident report needs a timeline of when the compromise happened, when it was detected and when it was contained, plus the scope of affected systems and data. Add the root cause, whether an unpatched vulnerability, stolen credentials or a misconfiguration, along with the evidence (logs, process dumps, hashes), the remediation steps taken and the lessons learned to prevent a repeat.

How do I find unauthorized users and SSH keys on a Linux server?

Print every authorized_keys file with find / -name authorized_keys -exec cat {} \; and list accounts with a login shell using grep -v "nologin\|false" /etc/passwd. Compare both against the users and keys the team actually created. Lock a suspicious account with passwd -l, remove unauthorized keys, and rotate every password and API key that was on the server.

Read how we handle it in Cybersecurity.