🔎 Security Auditing & Compliance

Security Series: Part 1 — Security Basics  |  Part 2 — SSH Hardening  |  Part 3 — Firewall Management  |  Part 4 — Auditing & Compliance

You Just Got Handed a System — Now What?

You inherit a server. Maybe it was built by someone who has left. Maybe it came from a vendor. Maybe it has been running unattended for years. The question is always the same: has this system been hardened at all, and what is actually running on it?

This page is a systematic audit workflow — the checks that answer that question in order of priority. Run through these and you will know exactly where the system stands and what needs to be fixed. The final example is a complete audit script you can drop on any RHEL or Debian system and run immediately.

Audit Priority Order

  1. Who can get in? — Accounts, SSH keys, sudo rights
  2. What is exposed? — Listening ports, running services
  3. Is there a firewall? — And is it actually blocking anything?
  4. Is SELinux/AppArmor on? — And enforcing?
  5. When were updates last applied? — How far behind is it?
  6. What has been running and for how long? — Uptime, services
  7. Are logs being kept? — And is anyone reading them?
  8. What does the filesystem look like? — SUID, world-writable, odd files

Examples

1
Who Can Get In — Accounts and Access
# How long has this system been up?
uptime
last reboot | head -5

# What accounts exist with login shells?
awk -F: '$7 !~ /nologin|false|sync|halt|shutdown/ {print $1, $3, $7}' /etc/passwd

# Any UID 0 accounts besides root?
awk -F: '$3 == 0 {print "UID-0:", $1}' /etc/passwd

# Any accounts with no password?
sudo awk -F: '$2 == "" {print "NO PASSWORD:", $1}' /etc/shadow

# Who has sudo?
sudo grep -v "^#\|^$\|^Defaults" /etc/sudoers
sudo grep -rh "ALL" /etc/sudoers.d/ 2>/dev/null

# Who is in the wheel/sudo group?
getent group wheel
getent group sudo

# What SSH keys are authorized?
sudo find /home /root -name "authorized_keys" -exec echo "=== {} ===" \; \
    -exec cat {} \; 2>/dev/null

# Who has logged in recently?
last | head -20
lastlog | grep -v "Never logged in" | head -20

# Any active sessions right now?
who
w
🚩 Red flags to look for:
2
What Is Exposed — Network Attack Surface
# What is listening on the network?
sudo ss -tulpn
sudo ss -tulpn | grep LISTEN

# What processes own those listening sockets?
sudo ss -tulpn | awk 'NR>1 {print $1, $5, $7}' | column -t

# Are any services listening on 0.0.0.0 that should be internal only?
sudo ss -tulpn | grep "0.0.0.0"

# What services are running?
systemctl list-units --type=service --state=running --no-pager

# What is enabled to start at boot?
systemctl list-unit-files --type=service --state=enabled --no-pager

# Check for unexpected web servers
sudo ss -tulpn | grep -E ":80|:443|:8080|:8443"

# Check for databases exposed on network
sudo ss -tulpn | grep -E ":3306|:5432|:27017|:6379"

# Check for remote management tools
sudo ss -tulpn | grep -E ":5900|:5901|:3389|:23|:512|:513"
🚩 Red flags:
3
Firewall, SELinux, and Update Status
# Is there a firewall running?
sudo firewall-cmd --state 2>/dev/null || echo "firewalld: not running"
sudo ufw status 2>/dev/null || echo "ufw: not running"
sudo iptables -L -n 2>/dev/null | head -20

# What does the firewall actually allow?
sudo firewall-cmd --list-all 2>/dev/null

# Is SELinux on and enforcing?
getenforce
sestatus | grep -E "status|mode|policy"

# When were packages last updated?
# RHEL:
sudo rpm -qa --last | head -20
sudo dnf history | head -10

# Debian/Ubuntu:
ls -lt /var/log/apt/ | head -5
cat /var/log/apt/history.log | tail -30

# How many security updates are pending?
sudo dnf updateinfo list security 2>/dev/null | wc -l
sudo apt list --upgradable 2>/dev/null | wc -l

# When was the OS installed?
sudo rpm -qi basesystem 2>/dev/null | grep "Install Date"
ls -la /lost+found    # creation time of root filesystem
sudo tune2fs -l /dev/sda1 2>/dev/null | grep "Filesystem created"
🚩 Red flags:
4
SSH Configuration Audit
# Check critical SSH settings
echo "=== SSH Configuration Audit ==="

grep -i "^PermitRootLogin" /etc/ssh/sshd_config
grep -i "^PasswordAuthentication" /etc/ssh/sshd_config
grep -i "^PermitEmptyPasswords" /etc/ssh/sshd_config
grep -i "^X11Forwarding" /etc/ssh/sshd_config
grep -i "^MaxAuthTries" /etc/ssh/sshd_config
grep -i "^AllowUsers\|^AllowGroups" /etc/ssh/sshd_config
grep -i "^Port" /etc/ssh/sshd_config
grep -i "^Protocol" /etc/ssh/sshd_config

# What port is SSH actually listening on?
sudo ss -tulpn | grep sshd

# Check SSH host key types (weak keys are a red flag)
ls -la /etc/ssh/ssh_host_*
sudo ssh-keygen -lf /etc/ssh/ssh_host_rsa_key.pub 2>/dev/null
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub 2>/dev/null

# Any recent failed login attempts?
sudo journalctl -u sshd --since "24 hours ago" | grep "Failed" | wc -l
sudo journalctl -u sshd --since "24 hours ago" | grep "Failed" | \
    awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
🚩 Red flags:
5
Filesystem and Process Anomalies
# SUID binaries -- compare against known good list
sudo find / -xdev -type f -perm -4000 -ls 2>/dev/null

# World-writable files outside /tmp
sudo find / -xdev -type f -perm -0002 ! -path "/tmp/*" -ls 2>/dev/null

# Files modified in the last 24 hours in sensitive locations
sudo find /etc /bin /sbin /usr/bin /usr/sbin -mtime -1 -ls 2>/dev/null

# Hidden files in unusual locations
sudo find / -xdev -name ".*" -not -path "/home/*" -not -path "/root/*" \
    -not -path "/proc/*" -not -path "/sys/*" -ls 2>/dev/null | head -20

# Processes running as root
ps aux | awk '$1 == "root" {print $1, $2, $11}' | head -20

# Processes with no associated binary (deleted executables -- sign of compromise)
sudo ls -la /proc/*/exe 2>/dev/null | grep "deleted"

# Unusual cron jobs
sudo ls -la /etc/cron* /var/spool/cron/ 2>/dev/null
sudo find /etc/cron* /var/spool/cron -type f -exec cat {} \; 2>/dev/null

# Check /tmp for suspicious executables
ls -la /tmp/
find /tmp /var/tmp -type f -executable -ls 2>/dev/null
🚩 Red flags:
6
Log Health Check
# Is logging working?
sudo systemctl status rsyslog 2>/dev/null || sudo systemctl status syslog
sudo systemctl status auditd

# How much log history exists?
ls -lh /var/log/
sudo du -sh /var/log/*

# Is journald keeping logs persistently?
sudo journalctl --disk-usage
ls -la /var/log/journal/

# Check for log gaps (sign of log clearing or system issues)
sudo journalctl --list-boots

# Are there any audit rules in place?
sudo auditctl -l
sudo cat /etc/audit/audit.rules 2>/dev/null
sudo cat /etc/audit/rules.d/*.rules 2>/dev/null

# Check for recent auth failures in auth log
sudo journalctl --since "7 days ago" | grep -i "failed\|invalid\|error" | wc -l

# Is logrotate configured and working?
ls -la /etc/logrotate.d/
sudo logrotate -d /etc/logrotate.conf 2>&1 | head -20
🚩 Red flags:
7
Installed Software and Package Integrity
# What packages are installed?
rpm -qa | sort > /tmp/installed-packages.txt    # RHEL
dpkg -l | sort > /tmp/installed-packages.txt    # Debian

# Any packages installed from outside official repos?
sudo rpm -qa --qf "%{NAME} %{VENDOR}\n" | grep -v "Red Hat\|CentOS\|Rocky\|Fedora" | sort
sudo apt list --installed 2>/dev/null | grep -v "automatic\|ubuntu\|debian"

# Verify package integrity -- files modified since install (RHEL)
sudo rpm -Va 2>/dev/null | grep -v "^......G\." | head -30
# Output codes: S=size, M=mode, 5=MD5, L=link, D=device, U=user, G=group, T=mtime

# Check for packages with known vulnerabilities
sudo dnf updateinfo list cves 2>/dev/null | head -20

# What repositories are configured?
sudo dnf repolist    # RHEL
cat /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null   # Debian

# Any suspicious kernel modules loaded?
lsmod | sort
# Compare against a known good system
💡 rpm -Va is your integrity checker. On RHEL systems, rpm -Va verifies every installed file against the package database. Files showing 5 in the output have a different MD5 hash than when installed — either legitimately modified config files or tampered binaries. Tampered binaries in /bin or /usr/bin are a serious red flag.
8
The Complete Inherited System Audit Script

Drop this on any system and run it as root for an immediate security snapshot:

#!/bin/bash
# inherited-system-audit.sh
# Quick security audit for a newly inherited Linux system
# Run as root: sudo bash inherited-system-audit.sh | tee /tmp/audit-$(hostname)-$(date +%Y%m%d).txt

HOSTNAME=$(hostname)
DATE=$(date)
SEP="========================================"

header() { echo ""; echo "$SEP"; echo "  $1"; echo "$SEP"; }

echo "$SEP"
echo "  SECURITY AUDIT: $HOSTNAME"
echo "  $DATE"
echo "$SEP"

header "SYSTEM INFO"
uname -a
cat /etc/os-release | grep -E "^NAME|^VERSION"
uptime
last reboot | head -3

header "ACCOUNTS WITH LOGIN SHELLS"
awk -F: '$7 !~ /nologin|false|sync|halt|shutdown/ {printf "  %-20s UID:%-6s %s\n", $1, $3, $7}' /etc/passwd

header "UID-0 ACCOUNTS (should be root only)"
awk -F: '$3 == 0 {print "  " $1}' /etc/passwd

header "ACCOUNTS WITH NO PASSWORD"
awk -F: '$2 == "" {print "  " $1}' /etc/shadow 2>/dev/null || echo "  (requires root)"

header "SUDO CONFIGURATION"
grep -v "^#\|^$\|^Defaults" /etc/sudoers | sed 's/^/  /'
find /etc/sudoers.d -type f -exec cat {} \; 2>/dev/null | grep -v "^#\|^$" | sed 's/^/  /'

header "WHEEL / SUDO GROUP MEMBERS"
getent group wheel 2>/dev/null | sed 's/^/  /'
getent group sudo  2>/dev/null | sed 's/^/  /'

header "AUTHORIZED SSH KEYS"
find /home /root -name "authorized_keys" 2>/dev/null | while read f; do
    echo "  === $f ==="
    cat "$f" | sed 's/^/  /'
done

header "LISTENING NETWORK PORTS"
ss -tulpn | grep LISTEN | sed 's/^/  /'

header "RUNNING SERVICES"
systemctl list-units --type=service --state=running --no-pager | grep "\.service" | \
    awk '{print "  " $1}' | head -30

header "FIREWALL STATUS"
firewall-cmd --state 2>/dev/null | sed 's/^/  /'
firewall-cmd --list-all 2>/dev/null | sed 's/^/  /'
ufw status 2>/dev/null | sed 's/^/  /'

header "SELINUX STATUS"
getenforce 2>/dev/null | sed 's/^/  /'
sestatus 2>/dev/null | grep -E "status|mode|policy" | sed 's/^/  /'

header "RECENT PACKAGE UPDATES (last 10)"
rpm -qa --last 2>/dev/null | head -10 | sed 's/^/  /'
ls -lt /var/log/apt/history.log 2>/dev/null | head -5

header "PENDING SECURITY UPDATES"
dnf updateinfo list security 2>/dev/null | wc -l | xargs echo "  RHEL security updates pending:"
apt list --upgradable 2>/dev/null | wc -l | xargs echo "  Debian upgradable packages:"

header "SSH CONFIGURATION HIGHLIGHTS"
grep -iE "^PermitRootLogin|^PasswordAuthentication|^PermitEmptyPasswords|^AllowUsers|^AllowGroups|^Port|^MaxAuthTries|^X11Forwarding" \
    /etc/ssh/sshd_config | sed 's/^/  /'

header "RECENT FAILED SSH LOGINS (last 24h)"
journalctl -u sshd --since "24 hours ago" 2>/dev/null | grep "Failed" | \
    awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10 | sed 's/^/  /'

header "SUID BINARIES"
find / -xdev -type f -perm -4000 -ls 2>/dev/null | sed 's/^/  /'

header "WORLD-WRITABLE FILES (outside /tmp)"
find / -xdev -type f -perm -0002 ! -path "/tmp/*" ! -path "/proc/*" -ls 2>/dev/null | \
    head -20 | sed 's/^/  /'

header "EXECUTABLES IN /tmp"
find /tmp /var/tmp -type f -executable -ls 2>/dev/null | sed 's/^/  /'
[ -z "$(find /tmp /var/tmp -type f -executable 2>/dev/null)" ] && echo "  None found (good)"

header "PROCESSES WITH DELETED BINARIES"
ls -la /proc/*/exe 2>/dev/null | grep "deleted" | sed 's/^/  /'
[ $? -ne 0 ] && echo "  None found (good)"

header "CRON JOBS (all users)"
for user in $(cut -f1 -d: /etc/passwd); do
    crontab -l -u "$user" 2>/dev/null | grep -v "^#\|^$" | \
        while read line; do echo "  [$user] $line"; done
done
find /etc/cron* /var/spool/cron -type f 2>/dev/null | \
    xargs grep -l "" 2>/dev/null | sed 's/^/  File: /'

header "AUDIT COMPLETE"
echo "  Review red flags above and compare against expected state."
echo "  Save this output: sudo bash inherited-system-audit.sh | tee /tmp/audit-$HOSTNAME-$(date +%Y%m%d).txt"
echo ""

Quick Reference — Red Flag Checklist

CheckCommandRed Flag
UID-0 accountsawk -F: '$3==0' /etc/passwdAnything other than root
Empty passwordssudo awk -F: '$2==""' /etc/shadowAny result
Root SSH logingrep PermitRootLogin /etc/ssh/sshd_configyes or not set to no
Password SSHgrep PasswordAuthentication /etc/ssh/sshd_configyes
Listening portssudo ss -tulpnDB/VNC/Telnet on 0.0.0.0
Firewallsudo firewall-cmd --statenot running
SELinuxgetenforcePermissive or Disabled
Updates pendingsudo dnf updateinfo list securityMany results
Deleted processesls -la /proc/*/exe | grep deletedAny result
Executables in /tmpfind /tmp -type f -executableAny result
Package integritysudo rpm -VaModified system binaries
Cron anomaliessudo crontab -l; ls /etc/cron*Unknown jobs as root

← Back to Security Index ↑ Back to EXPANDED