# Sat Mar 7 10:56:29 GMT 2026 #!/usr/bin/env bash # ============================================================================= # collect_intrussion_logs.sh # Incident snapshot script collects boot, wake, login, network and # filesystem evidence for post-incident review. # ============================================================================= # Determine script directory DIR="$(dirname "$(readlink -f "$0")")" # Build filename base: HOSTNAME_YYYY-MM-DD_HH-MM-SS SNAP_HOST=$(hostname -f 2>/dev/null || hostname) SNAP_DATE=$(date +"%Y-%m-%d_%H-%M-%S") SNAP_BASE="${SNAP_HOST}_${SNAP_DATE}" LOG="$DIR/${SNAP_BASE}.txt" ZIP="$DIR/${SNAP_BASE}.zip" # Redirect all output (stdout + stderr) to log.txt exec >"$LOG" 2>&1 # Disable pagers for journalctl, systemctl, less, etc. export SYSTEMD_PAGER=cat export PAGER=cat export LESS='-F -X' # ============================================================================= # Auto-detect network interfaces # ============================================================================= # Primary wired interface (first physical Ethernet, excludes lo/virtual/wifi) ETH_IF=$(ip -o link show | awk -F': ' ' $2 !~ /^(lo|vir|veth|docker|br-|virbr|tun|tap|dummy|bond|vlan|wl)/ { cmd = "cat /sys/class/net/" $2 "/type 2>/dev/null" cmd | getline type close(cmd) # type 1 = Ethernet if (type == "1") { print $2; exit } } ') # All wireless interfaces WIFI_IFS=$(ip -o link show | awk -F': ' ' $2 ~ /^wl/ { print $2 } ' | tr '\n' ' ') # All physical interfaces (wired + wifi, no loopback/virtual) ALL_IFS=$(ip -o link show | awk -F': ' ' $2 !~ /^(lo|vir|veth|docker|br-|virbr|tun|tap|dummy|bond)/ { print $2 } ' | tr '\n' ' ') # ============================================================================= # Helper functions # ============================================================================= # Timestamp helper ts() { date +"%F %T %z"; } # Run a simple command run() { echo "================================================================" echo "[$(ts)] CMD: $*" echo "----------------------------------------------------------------" "$@" echo } # Run a shell pipeline or complex command run_sh() { echo "================================================================" echo "[$(ts)] SHELL: $*" echo "----------------------------------------------------------------" bash -c "$*" echo } # Section header (no command execution) section() { echo "================================================================" echo "[$(ts)] >>> $*" echo "================================================================" echo } # ============================================================================= # SNAPSHOT START # ============================================================================= echo "=== INCIDENT SNAPSHOT START $(ts) ===" echo echo "Hostname : $(hostname -f 2>/dev/null || hostname)" echo "Kernel : $(uname -r)" echo "OS : $(grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d '\"' || uname -s)" echo "Uptime : $(uptime -p 2>/dev/null || uptime)" echo "Wired iface: ${ETH_IF:-}" echo "Wifi ifaces: ${WIFI_IFS:-}" echo "All ifaces : ${ALL_IFS:-}" echo # ============================================================================= # 1. Boot time and recent boot history # ============================================================================= run who -b run journalctl --list-boots --no-pager # ============================================================================= # 2. Previous boot how did it end? # ============================================================================= section "PREVIOUS BOOT last 60 lines (how did it end?)" journalctl --no-pager -b -1 -e 2>/dev/null | tail -60 || echo "(no previous boot log)" echo # ============================================================================= # 3. Full current boot log # ============================================================================= run journalctl --no-pager -b # ============================================================================= # 4. Wake / WOL / ACPI / RTC indicators # ============================================================================= run_sh 'dmesg | grep -i wake || true' run_sh 'journalctl --no-pager -b | grep -iE "wake|wol|acpi|rtc" || true' run cat /proc/acpi/wakeup || true run cat /sys/power/wakeup_count || true # ============================================================================= # 5. WOL status auto-detected interfaces # ============================================================================= section "WOL STATUS all physical interfaces" for IFACE in $ALL_IFS; do echo "--- ethtool $IFACE ---" if command -v ethtool &>/dev/null; then ethtool "$IFACE" 2>/dev/null || echo "(ethtool failed for $IFACE)" echo " Wake-on settings:" ethtool "$IFACE" 2>/dev/null | grep -i wake || echo " (no wake info)" else echo " (ethtool not installed)" fi echo done run_sh 'grep -rh -i "ff:ff:ff:ff:ff:ff" /var/log/ 2>/dev/null || true' run_sh 'grep -rh -i "magic" /var/log/ 2>/dev/null || true' # ============================================================================= # 6. Login history and authentication # ============================================================================= run last -F run lastb -F 2>/dev/null || echo "(lastb unavailable or /var/log/btmp missing)" run journalctl --no-pager -u ssh -u sshd run_sh 'journalctl --no-pager -b | grep -iE "ssh|Accepted|Failed|Invalid|authentication|publickey|password" || true' run_sh 'grep -iE "Accepted|Failed|Invalid|authentication" /var/log/auth.log 2>/dev/null || true' run_sh 'journalctl --no-pager -b | grep -i sudo || true' run_sh 'grep -i sudo /var/log/auth.log 2>/dev/null || true' # ============================================================================= # 7. Active sessions # ============================================================================= run who run w run loginctl list-sessions 2>/dev/null || true # ============================================================================= # 8. Services started after boot # ============================================================================= run_sh 'journalctl --no-pager -b | grep -i "Started" || true' # ============================================================================= # 9. Scheduled tasks cron + systemd timers (all users) # ============================================================================= run journalctl --no-pager -u cron run_sh 'grep -i cron /var/log/syslog 2>/dev/null || true' section "CRON FILES /etc/cron* and /var/spool/cron" run_sh 'ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/ 2>/dev/null || true' run_sh 'find /etc/cron* -type f 2>/dev/null | sort | while read f; do echo "=== $f ==="; cat "$f"; echo; done || true' section "PER-USER CRONTABS" for UNAME in root $(awk -F: '$3 >= 1000 && $7 !~ /nologin|false/ {print $1}' /etc/passwd); do CRONTAB_FILE="/var/spool/cron/crontabs/$UNAME" if [ -f "$CRONTAB_FILE" ]; then echo "--- crontab for $UNAME ---" cat "$CRONTAB_FILE" echo fi done run systemctl list-timers --all --no-pager 2>/dev/null || true # ============================================================================= # 10. Processes sorted by start time # ============================================================================= run ps auxf --sort=start_time # ============================================================================= # 11. Network connections and interface details # ============================================================================= run ss -tupn run lsof -i -n -P 2>/dev/null || true run ip addr show run ip route show section "INTERFACE LINK DETAILS" for IFACE in $ALL_IFS; do echo "--- $IFACE ---" ip link show "$IFACE" 2>/dev/null || true echo done run_sh 'journalctl --no-pager -b | grep -iE "connect|network|dhcp" || true' # ============================================================================= # 12. Filesystem anomalies # ============================================================================= section "FILES MODIFIED OUTSIDE PACKAGE MANAGER (newer than /var/log/dpkg.log)" find /etc /bin /sbin /usr/bin /usr/sbin -newer /var/log/dpkg.log -type f 2>/dev/null \ | grep -v '\.pyc$' \ || echo "(none found or dpkg.log missing)" echo section "SUID/SGID BINARIES" find / -xdev -perm /6000 -type f 2>/dev/null | sort echo section "RECENTLY MODIFIED FILES IN TEMP DIRECTORIES" run ls -laht /tmp run ls -laht /var/tmp run_sh 'ls -laht /dev/shm 2>/dev/null || true' section "FILES MODIFIED SINCE BOOT home dirs and /root" find /root /home -maxdepth 4 -newer /proc/1 -type f 2>/dev/null \ | grep -vE '\.cache|\.local/share/recently|\.xsession-errors' \ || echo "(none found)" echo # ============================================================================= # 13. Package integrity check (Debian/Ubuntu) # ============================================================================= section "PACKAGE INTEGRITY CHECK (debsums)" if command -v debsums &>/dev/null; then debsums -c 2>/dev/null || echo "(debsums reported errors above)" else echo "(debsums not installed consider: apt install debsums)" fi echo # ============================================================================= # 14. Kernel modules # ============================================================================= run lsmod run_sh 'dmesg | grep -iE "module|insmod|rmmod|taint" || true' run_sh 'journalctl --no-pager -b | grep -iE "module|insmod|rmmod|taint" || true' # ============================================================================= # 15. Shell history # ============================================================================= section "SHELL HISTORY FILES (last 50 lines each)" for UNAME in root $(awk -F: '$3 >= 1000 && $7 !~ /nologin|false/ {print $1}' /etc/passwd); do UHOME=$(getent passwd "$UNAME" | cut -d: -f6) for HIST in "$UHOME/.bash_history" "$UHOME/.zsh_history"; do if [ -f "$HIST" ]; then echo "--- $HIST ---" tail -50 "$HIST" echo fi done done # ============================================================================= # 16. User accounts, sudoers, sensitive file modifications # ============================================================================= run_sh 'journalctl --no-pager -b | grep -i audit || true' section "USER AND GROUP LIST" run_sh 'cut -d: -f1,3,4,6,7 /etc/passwd' section "SUDOERS CONFIGURATION" run_sh 'grep -v "^#" /etc/sudoers 2>/dev/null || true' run_sh 'cat /etc/sudoers.d/* 2>/dev/null || true' section "SENSITIVE AUTH FILES MODIFIED SINCE BOOT" find /etc -maxdepth 2 \( -name passwd -o -name shadow -o -name sudoers -o -name group \) \ -newer /proc/1 -type f 2>/dev/null \ && echo "WARNING: auth files modified since last boot!" \ || echo "(no changes to passwd/shadow/sudoers/group since boot)" echo # ============================================================================= # SNAPSHOT END # ============================================================================= echo "=== INCIDENT SNAPSHOT END $(ts) ===" echo # ============================================================================= # 17. Create ZIP archive # ============================================================================= zip -j "$ZIP" "$LOG" # ============================================================================= # 18. Send ZIP as MIME attachment # ============================================================================= SUBJECT="Incident snapshot log - $(hostname) - $(date '+%d-%m-%Y %H:%M:%S')" echo "Incident snapshot attached." | mutt -s "$SUBJECT" -a "$ZIP" -- andrzejl@andrzejl.eu # ============================================================================= # 19. Cleanup ZIP and LOG # ============================================================================= rm -f "$ZIP" "$LOG"