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.
# 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
ALL=(ALL) NOPASSWD: ALL in sudo# 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"
0.0.0.0 — should be 127.0.0.1# 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"
# 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
PermitRootLogin yes — fix immediatelyPasswordAuthentication yes — should be key-onlyAllowUsers or AllowGroups restriction# 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
(deleted) in their exe path/tmp or /var/tmp# 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
# 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 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.
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 ""
| Check | Command | Red Flag |
|---|---|---|
| UID-0 accounts | awk -F: '$3==0' /etc/passwd | Anything other than root |
| Empty passwords | sudo awk -F: '$2==""' /etc/shadow | Any result |
| Root SSH login | grep PermitRootLogin /etc/ssh/sshd_config | yes or not set to no |
| Password SSH | grep PasswordAuthentication /etc/ssh/sshd_config | yes |
| Listening ports | sudo ss -tulpn | DB/VNC/Telnet on 0.0.0.0 |
| Firewall | sudo firewall-cmd --state | not running |
| SELinux | getenforce | Permissive or Disabled |
| Updates pending | sudo dnf updateinfo list security | Many results |
| Deleted processes | ls -la /proc/*/exe | grep deleted | Any result |
| Executables in /tmp | find /tmp -type f -executable | Any result |
| Package integrity | sudo rpm -Va | Modified system binaries |
| Cron anomalies | sudo crontab -l; ls /etc/cron* | Unknown jobs as root |