Linux runs most cloud workloads, web servers and network appliances, yet many incident responders are far less fluent in its artefacts than in Windows event logs and the registry. Evidence on a Linux host is spread across systemd journals, auditd records, text logs whose paths differ by distribution, shell history that is written only when a shell exits, cron and systemd units, SSH key files and the live state in /proc, and much of it disappears on reboot or is easy for an intruder to alter. This guide is for DFIR practitioners, SOC analysts and platform engineers who need to investigate a compromised Linux server or virtual machine. It covers collection order, the artefacts that answer each investigative question, persistence locations, anti-forensics, tooling and how to prepare hosts so the evidence exists. General DFIR method is in the Digital Forensics (DFIR) Guide; this guide is Linux specific.
Key takeaways
- Collect volatile state before anything else. Running processes, network connections, deleted-but-running binaries and memory are lost on reboot, and many Linux implants live only in memory or in
/tmpand/dev/shm. - Know which logs the host actually had. Journald may be volatile, auditd may not be installed and text log paths differ between Debian and Red Hat families, so establish the logging baseline before drawing conclusions from absence.
- Persistence has a short list of homes. Cron, systemd units and timers, SSH authorized_keys, shell start-up files, PAM modules, preload libraries and kernel modules cover most real cases.
- Shell history is weak evidence. It is written on exit, has no timestamps unless configured and is trivially cleared; corroborate with auditd EXECVE records and process accounting.
- Machine credentials on the host are part of the scope. SSH private keys, cloud credentials, tokens in environment files and service account secrets must be inventoried and rotated, not just the user passwords.
Collection order and preserving evidence
NIST SP 800-86, Guide to Integrating Forensic Techniques into Incident Response (Final, 2006), frames forensics from an IT rather than law enforcement view and remains the baseline reference for integrating collection into incident response. On Linux, the practical order is from most to least volatile:
- Record the context: hostname, time and time zone, clock offset from a trusted source, uptime and who is logged in. Note every command you run with a timestamp.
- Memory: acquire RAM before running large tool sets. LiME is a loadable kernel module that writes memory to disk or over TCP; its documentation recommends the
limeorpaddedformats overraw, and warns that the digest and compression options disturb more of the target's memory. The module must match the running kernel, so prebuild modules for your standard kernels. On cloud VMs, a provider snapshot that includes memory, where available, avoids loading a module. See the Memory Forensics Guide and the Volatility 3 Guide. - Live state: process list with full command lines and parent relationships, open network sockets with owning processes, loaded kernel modules, mounts, logged-in users, and for each suspicious process its
/proc/<pid>/exe,cmdline,environandmaps. A process whoseexelink ends in "(deleted)" is running from a binary that has been removed from disk; copy it from/procwhile it is still running. - Triage collection: logs, configuration, user artefacts and a file system timeline bodyfile.
- Disk: snapshot or image the volume. In the cloud, snapshot the disk and analyse a copy attached to a forensic instance, never the original.
Hash everything you collect, write output to external or network storage rather than the suspect disk, and record chain of custody. Collection on a live host always changes it; the aim is to change it as little as possible and document what you did. Note that some journalctl operations such as vacuum, rotate and flush change journal state, so run analysis against copies.
Artefacts by investigative question
| Question | Primary artefacts | Notes |
|---|---|---|
| Who logged in, from where, when? | /var/log/auth.log (Debian, Ubuntu) or /var/log/secure (RHEL family); /var/log/wtmp (read with last); /var/log/btmp (failed logins, lastb); /var/run/utmp (current sessions); journald sshd entries; auditd USER_LOGIN | wtmp records carry user, remote host and time; utmp must not be writable by other users or fake records can be created |
| What commands ran? | auditd EXECVE and SYSCALL records; ~/.bash_history and other shell histories; journald for sudo; process accounting if enabled | History is written on shell exit and only has timestamps if HISTTIMEFORMAT was set |
| What was privileged? | sudo entries in auth.log or secure; /etc/sudoers and /etc/sudoers.d/; auditd records with euid 0; setuid files | Compare sudoers with configuration management |
| What persisted? | Cron, systemd units and timers, authorized_keys, shell profiles, PAM, /etc/ld.so.preload, kernel modules | See the persistence table below |
| What files changed? | File system timeline (modify, access, change and on ext4 birth times); package verification against the package database; web roots and /tmp, /var/tmp, /dev/shm | Timestamps can be forged; inode change time is harder to set than modify time |
| What did it talk to? | Live sockets; firewall and flow logs; DNS resolver logs; application logs; auditd connect records if rules exist | Linux keeps no native connection history; external telemetry matters |
| What services were exposed and exploited? | Web server access and error logs; application logs; journald for each unit | See the Web Server Access Log Detection Guide |
Systemd journal and auditd
- Journald storage: journals are persistent only if
/var/log/journalexists or Storage=persistent is set; otherwise they live in/run/log/journaland are lost on reboot. Check this first, because "no journal entries before boot" may simply mean volatile storage. - Reading journals offline:
journalctl --directory=,--file=,--root=or--image=read copied journals or mounted images. Use--utcfor cross-host timelines,--list-bootsand-bto scope boots, field matches such as_SYSTEMD_UNIT=sshd.service,_COMM=and_UID=, and-o jsonor-o exportto keep every field. - Journal integrity:
--verifychecks internal consistency, and with Forward Secure Sealing (--setup-keysrun before an incident, verified with--verify-key=) can show whether sealed entries were altered.--headerhelps spot out-of-order entries from a changed clock. - auditd: on RHEL the audit log is
/var/log/audit/audit.log, with each event split into records (SYSCALL, EXECVE, PATH, CWD, PROCTITLE) that share a timestamp and event ID. Useausearch -ito interpret values,-m USER_LOGINor-k <key>to filter,-tsfor time, andaureportfor summaries. The value of auditd in an investigation depends entirely on the rules that were loaded; record them from/etc/audit/rules.d/. - Audit tampering: look for auditd stopped, rules removed or
auditctl -e 0in records and journals; ATT&CK v20 lists execution of auditctl and stopping auditd as log sources for this behaviour. Clearing logs maps to T1685.006 Clear Linux or Mac System Logs.
For configuring auditd before an incident, see the Linux Logging and auditd for Defenders Guide.
Persistence locations to check
| Mechanism | ATT&CK | Where to look |
|---|---|---|
| Cron | T1053.003 | /etc/crontab, /etc/cron.d/, /etc/cron.{hourly,daily,weekly,monthly}/, user crontabs under /var/spool/cron/ (Debian uses /var/spool/cron/crontabs/); cron execution in syslog or journal |
| Systemd services | T1543.002 | Unit files in /etc/systemd/system/, /lib/systemd/system/ or /usr/lib/systemd/system/, and user units in ~/.config/systemd/user/; ExecStart pointing to /tmp, hidden directories or interpreters |
| Systemd timers | T1053.006 | *.timer files in the same directories; list active timers on the live host |
| SSH authorized keys | T1098.004 | ~/.ssh/authorized_keys for every account including root and service accounts; AuthorizedKeysFile overrides in sshd_config |
| Shell start-up files | T1546.004 | ~/.bashrc, ~/.bash_profile, ~/.profile, /etc/profile, /etc/profile.d/, /etc/bash.bashrc |
| Dynamic linker preload | T1574.006 | /etc/ld.so.preload, which the ld.so manual describes as usually undesirable; LD_PRELOAD in service environments |
| PAM modules | T1556.003 | /etc/pam.d/ and module directories; modules not owned by any package |
| Kernel modules and rootkits | T1547.006, T1014 | Loaded modules versus those on disk and in packages; /etc/modules-load.d/; memory analysis for hidden modules |
| Local accounts | T1136.001 | /etc/passwd, /etc/shadow and /etc/group for new UID 0 accounts, new shells on service accounts, recent password changes |
| Setuid binaries | T1548.001 | Setuid and setgid files outside package ownership |
The most reliable way to separate malicious from normal is package verification: files under system paths that are not owned by any package, or whose hash differs from the package database, deserve review first. Compare with configuration management or a known-good image where you have one.
Anti-forensics and how to see through it
- Cleared history: an empty or truncated
.bash_history, HISTFILE unset (Bash then saves nothing) or history symlinked to/dev/nullare themselves indicators (T1070.003). Recover command evidence from auditd EXECVE, sudo logs and memory. - Edited text logs: gaps in syslog timestamps, a missing rotation file or a log shorter than its rotated predecessor. Off-host log copies are the only reliable answer.
- Timestomping: modify and access times set to match neighbouring system files (T1070.006). Inode change time and ext4 birth time are harder to alter and often betray it.
- Deleted binaries: malware that deletes itself after launch still runs from memory; recover it from
/proc/<pid>/exeon the live host. - Rootkits: user-space preload rootkits hide files and processes from normal tools. Compare live tool output with memory analysis and with an offline view of the disk.
- Memory-only payloads in tmpfs:
/dev/shmand/runvanish on reboot; collect them in the live phase.
Tooling
| Need | Option | Notes |
|---|---|---|
| Live triage collection | UAC (Unix-like Artifacts Collector) | Apache 2.0; supports Linux, ESXi, macOS, BSDs, Solaris, AIX and NetScaler; collection profiles such as ir_triage and full; respects order of volatility; collects processes even without a binary on disk and a bodyfile |
| Fleet collection and hunting | Velociraptor | Query many hosts for the same artefact. See the Velociraptor Guide |
| Memory acquisition | LiME | GPL-2.0 kernel module; local or TCP output |
| Memory analysis | Volatility 3 | Needs a symbol table for the exact kernel |
| Timeline | Plaso and file system bodyfiles | See the Plaso Guide and the Forensic Timeline Analysis Guide |
| Journals and audit | journalctl, ausearch, aureport | Run against copies with offline options |
Containers add their own layers: overlay file systems, short-lived processes and logs held by the runtime. See the Container and Kubernetes Forensics Guide.
Where identity fits
Linux servers hold the machine credentials that turn one compromised host into many. Inventory and treat as exposed: SSH private keys in ~/.ssh/ and their entries in other hosts' authorized_keys, cloud CLI credential files and instance metadata access, tokens and passwords in .env files and systemd EnvironmentFile entries, Kubernetes service account tokens, database connection strings and CI runner tokens. Check auth logs on other hosts for the same keys being used (T1021.004), and query the cloud provider's audit log for the instance role being used from outside the instance. See the SSH Key Management Guide.
A practical investigation workflow
- Scope and contain without destroying evidence: isolate the host at the network or security group level rather than powering it off.
- Acquire volatile data: memory, then live state and suspicious process binaries from
/proc. - Run triage collection: UAC or an equivalent to external storage, and snapshot the disk.
- Establish the logging baseline: journald persistence, auditd presence and rules, log rotation and off-host forwarding.
- Find the entry point: authentication logs, web and application logs, and exposed service versions against known exploited vulnerabilities.
- Build a timeline: merge logs, journal, audit and file system times in UTC.
- Enumerate persistence: walk the persistence table and verify packages.
- Trace credentials and lateral movement: keys and secrets on the host, and their use elsewhere.
- Eradicate and recover: rebuild from a known-good image rather than cleaning in place, rotate every exposed credential and monitor for reuse.
Preparing Linux hosts before an incident
- Persistent journals and forwarding: create
/var/log/journalor set persistent storage, and forward logs off-host. - auditd with useful rules: start from the sample rule sets shipped with the audit package (Red Hat ships them in
/usr/share/audit/sample-rules/, and notes they are not exhaustive), keep audit logs on a separate mount and set log handling to keep logs. - Shell history with timestamps: set HISTTIMEFORMAT and histappend globally; treat it as a convenience, not a control.
- Forward Secure Sealing: set up journal sealing keys before you need them.
- Prebuilt collection kits: LiME modules for your kernels, UAC and symbol tables stored ready to use.
- Time synchronisation: consistent, monitored time sources so timelines from different hosts align.
Decision guidance
- Live response or snapshot only: for suspected memory-resident malware, rootkits or active intruders, live response first. For a single cloud VM with persistent logs off-host and no sign of in-memory implants, a disk snapshot may be enough.
- Clean or rebuild: rebuild. In-place cleaning of a Linux host with root-level compromise cannot prove a clean state, as appliance integrity tools failing in the Ivanti Connect Secure exploitation illustrated.
- Small teams: standardise on one triage collector and a written runbook, and make sure logs leave the host.
- Large estates: use fleet tooling to collect the same artefacts across all hosts sharing an image or credential, because Linux compromises often spread through shared SSH keys.
- Appliances: many network and security appliances run Linux but restrict shell access; collection must use the vendor's supported methods. See the Edge Device Compromise Investigation Playbook.
Measuring readiness
- Persistent journal coverage: percentage of Linux hosts with persistent journals and off-host forwarding.
- auditd coverage: percentage of servers running auditd with the standard rule set loaded.
- Collection kit currency: percentage of production kernels with a prebuilt memory module and symbol table.
- Time to triage: minutes from decision to a complete triage package for one host.
- Credential inventory: percentage of hosts whose SSH keys and secrets are inventoried, so rotation scope is known.
Common failure patterns
- Rebooting first: memory, tmpfs content, volatile journals and deleted running binaries are lost.
- Trusting tools on the suspect host: a rootkit or modified binaries can lie; use trusted static tools and cross-check with memory and offline disk analysis.
- Reading absence as innocence: no auditd records may mean no rules, and no journal history may mean volatile storage.
- Ignoring performance anomalies: the XZ Utils backdoor was found because SSH logins used unexpected CPU and were slower than usual, not through logs or signatures.
- Forgetting machine credentials: rebuilding the host while leaving its SSH keys and cloud credentials valid lets the intruder walk back in.
- Mixed time zones: syslog in local time, journals and cloud logs in UTC; timelines go wrong unless everything is normalised.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | RS.AN-03, RS.AN-06, RS.AN-07 | Analysis of what happened; recording investigation actions; preserving evidence integrity and provenance |
| NIST SP 800-53 Rev. 5 | IR-4, IR-5, AU-9, AU-12, SI-7 | Incident handling and monitoring, log protection and generation, integrity checking |
| NIST SP 800-86 | Whole document | Integrating forensic techniques into incident response |
| ISO/IEC 27001:2022 | Annex A 5.28, 8.15 | Collection of evidence; logging |
| MITRE ATT&CK v20 | T1053.003, T1543.002, T1098.004, T1574.006, T1556.003, T1070.003, T1685.006 | Linux persistence and anti-forensic techniques covered |
| MITRE D3FEND | D3-FA File Analysis, D3-PA Process Analysis, D3-FIM File Integrity Monitoring | Defensive analysis techniques used |
Practitioner checklist
- Isolate suspected Linux hosts at the network layer instead of shutting them down.
- Acquire memory with a prebuilt module before running broad collection.
- Capture processes, sockets, modules and binaries of suspicious processes from
/proc. - Run a triage collector to external storage, hash the output and snapshot the disk.
- Record whether journald was persistent, which auditd rules were loaded and where logs were forwarded.
- Walk every persistence location and verify system files against the package database.
- Build a single UTC timeline from logs, journal, audit and file system data.
- Inventory and rotate SSH keys, cloud credentials and secrets found on the host.
- Rebuild from a known-good image and monitor for reuse of old credentials.
Standards and references
- NIST: SP 800-86 Guide to Integrating Forensic Techniques into Incident Response
- systemd: journalctl manual
- Red Hat: RHEL 9 Security Hardening, Auditing the system
- Linux man-pages: utmp(5)
- Linux man-pages: ld.so(8)
- GNU: Bash Reference Manual, Bash History Facilities
- UAC project: Unix-like Artifacts Collector
- LiME project: Linux Memory Extractor
Related NHI Mgmt Group resources: Linux Detection and Response Guide · Digital Forensics (DFIR) Guide · Linux Server Hardening Guide · Cloud Forensics Guide · Memory Forensics Guide