/usr/bin, /etc/ssh, or /etc/cron.d were modified after your known-good baseline. This is the integrity layer.ls, ps, netstat, find. The tools you use to investigate are themselves compromised. Only an out-of-band baseline can detect this.chattr +i adds a local layer but is not sufficient alone./etc/aide/aide.conf, exclude directories that change constantly. !/var/log, !/var/run, !/proc, !/sys. Focus monitoring on /usr/bin, /etc/ssh, /etc/cron.d, /etc/pam.d.
aide --check returns 0 for no changes, 1 for changes detected, 2 for errors. Automate alerting in /etc/cron.daily/aide-check: mail results when exit code is non-zero.
aideinit on a system that may already be compromised makes the compromise the baseline. Always initialize immediately after a fresh, verified deployment.
-w sets the watch path. -p wa watches for write (w) and attribute changes (a). -k assigns a searchable key tag. The key is what you use with ausearch -k to find events quickly./usr/bin/python3 is expected. A change to /usr/bin/ls after no package updates is not. Every AIDE alert starts here.ausearch -k gives you the PID, the executable, and the user. Cross-reference with journalctl for the surrounding context./usr/bin, /usr/sbin, /etc/ssh, /etc/pam.d should never change without an explicit package update or configuration change. A change to these paths with no package manager activity is a strong indicator of compromise.us% = user-space problem; identify with top -bn1 sorted by CPU. High wa% = I/O wait; the bottleneck is disk, not CPU. High sy% = excessive syscalls; investigate with strace.free column is always small and that is fine. The available column is the real answer. Non-zero si/so in vmstat is the real memory pressure signal.nproc gives core count. sar gives historical baseline. Never diagnose without knowing what "normal" looks like.us user space · sy kernel · wa I/O wait · st hypervisor steal.wa = disk bottleneck. High st = noisy neighbor on a VM.
r > CPU count = CPU saturated. b > 0 = I/O bottleneck. si/so > 0 = swapping = memory exhaustion. wa > 20 = disk is the limit.
sar gives you the performance record for that window. Look for CPU spike (cryptominer), sudden I/O spike (exfiltration), or memory exhaustion (runaway process). If sar is not running, you have no historical view — the evidence is gone.
top shows 90%+ CPU. The process name may be disguised as kworker or a legitimate-looking name.ps aux --sort=-%cpu | head -10. Check the process binary path with ls -la /proc/PID/exe. Run AIDE check on the binary.sar -d shows a large write burst at 03:14 AM when no scheduled jobs were running. Could be data exfiltration staging.journalctl --since "03:10" --until "03:20" to find the source. Cross-reference with ausearch if auditd was watching the target directory.top shows 8 processes in uninterruptible sleep. System appears frozen. Cannot kill with SIGKILL. Common cause: hung NFS mount, failing disk.iostat -xz 2 to check disk error counters. journalctl -k -p err for kernel errors. Check dmesg for I/O errors.sudo mkdir -p /var/log/journal
Then set Storage=persistent in /etc/systemd/journald.conf and restart systemd-journald.
journalctl --disk-usage shows how much space the journal is using. Clean old entries with journalctl --vacuum-time=30d. Set SystemMaxUse=2G in journald.conf for automatic capping.
@ = UDP: fast, fire-and-forget, no delivery guarantee. Double @@ = TCP: connection-oriented, detects delivery failure. For a SIEM feeding security investigations, use TCP. For high-volume telemetry where loss is acceptable, UDP./etc/logrotate.conf and /etc/logrotate.d/ control rotation. Standard pattern: daily rotation, 30-day retention, compress old files. Without logrotate, /var/log/ fills the disk and takes the system down.
kern kernel · auth/authpriv authentication · cron cron jobs · daemon system daemons · local0..local7 custom applications. Use logger -t myapp -p local0.info to emit from scripts.
*.* all facilities, all priorities. *.err all facilities, error and above. auth.* all auth messages. *.warning;auth.none all warnings except auth. kern.=crit kernel at exactly crit (not above).
sar at 03:14 and an error in journalctl at 03:12 are correlated events. The timestamp overlap is the evidence. Without both, neither finding is actionable./etc/sudoers changed. journalctl tells you which user was active at that timestamp. Together they prove whether the change was authorized or malicious.ForwardToSyslog=yes in journald.conf and @@siem:514 in rsyslog.conf are not optional.sar data gives you the exact minute performance changed. Cross-reference with the AIDE-detected file change timestamp to narrow the compromise window to minutes, not days.aideinit after the fact. The compromise becomes the baseline. Future checks show nothing because the attacker's changes are now "normal."/proc change constantly. Operators ignore the noise, defeating the purpose of FIM.!/var/log, !/proc, !/sys, !/dev, !/var/run in /etc/aide/aide.conf. Focus on /usr/bin, /etc/ssh, /etc/pam.d.nproc might say 8 cores, making 6.0 light utilization. Or it might say 4, making 6.0 saturation.sysstat on every server. Always run nproc before interpreting load average. Use sar -u to establish historical norms before diagnosing deviations./run/log/journal/ (RAM-backed). All evidence from before the reboot is gone.mkdir -p /var/log/journal and set Storage=persistent in journald.conf. Also forward to rsyslog: logs that live only locally are still vulnerable to root-level deletion.sudo aide --check --verbose=2
sudo auditctl -l
sar -u 1 3
iostat -xz 2 2
journalctl -b --disk-usage
rsyslogd -N1