You’re probably thinking auditing Linux security is about checking if sshd is running or if firewalld is enabled. That’s just the surface. The real game is understanding how a compromised credential or a misconfigured service can unravel your entire system’s trust, even if all the obvious boxes are checked.
Let’s walk through a practical audit, not with abstract principles, but with concrete commands and what to look for.
1. User and Group Auditing
What’s Broken: A user with excessive privileges or an orphaned account can be an entry point for attackers.
Diagnosis:
-
Check for accounts with UID < 1000 (system accounts) that are unexpectedly active or have login shells:
getent passwd | awk -F: '$3 < 1000 && $7 ~ "/bin/bash|/bin/sh" {print $1, $3, $7}'Why it works: UIDs below 1000 are typically reserved for system services. If a service account has a shell, it’s a potential vulnerability.
-
Identify users with UID 0 (root privileges) that aren’t root:
getent passwd | awk -F: '$3 == 0 && $1 != "root" {print $1, $3}'Why it works: Only the
rootuser should have UID 0. Any other account with this UID has full administrative control. -
List users with no password set (should be rare for interactive users):
getent passwd | awk -F: -v OFS=":" '$2 == "" {print $1, $3, $4}'Why it works: An empty password field means the user can log in without authentication if other mechanisms allow it.
-
Check for groups with no members:
getent group | awk -F: '$4 == "" {print $1}'Why it works: Orphaned groups are just noise, but can sometimes indicate incomplete cleanup from removed users.
Fixes:
-
For unexpected system accounts with shells, change their shell to
/sbin/nologinor remove them if they’re not needed:usermod -s /sbin/nologin <username> userdel <username>Why it works: Disables interactive login for service accounts.
-
For users with UID 0 other than root, immediately change their UID and remove their root privileges:
usermod -u 1001 <username>Why it works: Reassigns the user to a non-privileged UID, revoking root access.
-
Set a strong password for any user that legitimately needs one and doesn’t have one. For service accounts, ensure they don’t have interactive shells and use key-based authentication if needed.
2. SSH Configuration Audit
What’s Broken: Weak SSH configurations, like password authentication or outdated protocols, are a prime target for brute-force attacks.
Diagnosis:
-
Check
PermitRootLoginsetting in/etc/ssh/sshd_config:grep PermitRootLogin /etc/ssh/sshd_configWhy it works: If it’s set to
yesorprohibit-password(and you’re relying on passwords), it’s a risk. -
Check
PasswordAuthenticationsetting:grep PasswordAuthentication /etc/ssh/sshd_configWhy it works: If it’s
yes, your server is vulnerable to password guessing. -
Check
Protocolsetting:grep Protocol /etc/ssh/sshd_configWhy it works: Protocol 1 is deprecated and insecure. It should be
2. -
Check for weak ciphers, MACs, and KexAlgorithms: This is more involved and often requires specialized tools or careful manual inspection of
/etc/ssh/sshd_configfor lines likeCiphers,MACs,KexAlgorithms.
Fixes:
-
Disable root login over SSH:
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_configWhy it works: Prevents direct root logins, forcing users to log in as a regular user and
suorsudoto root. -
Disable password authentication (use SSH keys):
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_configWhy it works: Eliminates brute-force password attacks entirely by requiring cryptographic keys.
-
Ensure SSH Protocol 2 is used:
sed -i 's/#Protocol 2/Protocol 2/' /etc/ssh/sshd_configWhy it works: Enforces the use of the secure SSHv2 protocol.
-
Restart SSH service:
systemctl restart sshdWhy it works: Applies the configuration changes.
3. File Permissions Audit
What’s Broken: Sensitive files (like /etc/shadow, /etc/sudoers) with world-writable or group-writable permissions can be tampered with.
Diagnosis:
-
Check permissions on
/etc/shadow:ls -l /etc/shadowWhy it works: Should be owned by
root:shadowand have permissions0640or0644. -
Check permissions on
/etc/sudoersand/etc/sudoers.d/*:ls -l /etc/sudoers /etc/sudoers.d/Why it works: Should be owned by
root:rootand have permissions0440. -
Identify world-writable files in critical directories:
find /etc -perm -o+w -type f 2>/dev/null find /usr/local/bin -perm -o+w -type f 2>/dev/nullWhy it works: World-writable files can be modified by any user on the system.
Fixes:
-
Correct permissions for
/etc/shadow:chown root:shadow /etc/shadow chmod 0640 /etc/shadowWhy it works: Restricts read access to root and the shadow group, preventing unauthorized access to password hashes.
-
Correct permissions for
/etc/sudoers:chown root:root /etc/sudoers chmod 0440 /etc/sudoersWhy it works: Ensures only root can read the sudoers configuration. Never edit this file directly with a text editor; always use
visudo. -
Remove world-writable permissions from unnecessary files:
chmod o-w /path/to/world/writable/fileWhy it works: Revokes write access for "others" (all users not owner/group).
4. Running Services and Network Ports
What’s Broken: Unnecessary services listening on network ports expose attack surfaces.
Diagnosis:
-
List all listening network ports and the processes using them:
ss -tulnpWhy it works: Shows which services are active and accessible over the network.
-
Check for services running as root that shouldn’t be: This is harder to automate with a single command but look for unusual processes in the
ss -tulnpoutput that are running as root.
Fixes:
-
Stop and disable unnecessary services:
systemctl stop <service_name> systemctl disable <service_name>Why it works: Prevents the service from starting on boot and immediately stops it from running.
-
Configure firewall rules: If a service must be running but only needs to be accessible from specific IPs, configure
firewalldoriptablesaccordingly.firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="80" protocol="tcp" accept' firewall-cmd --reloadWhy it works: Restricts network access to only authorized sources.
5. Auditd Configuration
What’s Broken: Without proper auditing, you won’t know when or how a compromise occurred, making incident response impossible.
Diagnosis:
-
Check if
auditdis running:systemctl status auditdWhy it works: If it’s not running, no system calls are being logged.
-
Examine the audit rules in
/etc/audit/rules.d/*.rules:cat /etc/audit/rules.d/*.rulesWhy it works: This is the configuration that dictates what is logged. A minimal configuration is a security risk.
Fixes:
-
Ensure
auditdis enabled and running:systemctl enable auditd systemctl start auditdWhy it works: Activates the audit daemon.
-
Implement a robust auditd rule set. This is a deep topic, but a good starting point includes logging:
- All executed commands (
-a always,exit -F arch=b64 -S execve -k exec). - Modifications to critical system files (
-w /etc/passwd -p wa -k identity). - Changes to user accounts (
-w /etc/shadow -p wa -k identity,-w /etc/group -p wa -k identity). - Privilege escalation (
-a always,exit -F arch=b64 -S setuid -k perm_mod). - Network configuration changes.
Why it works: These rules ensure that critical security-relevant events are recorded, providing an audit trail for investigations.
- All executed commands (
After fixing all of the above, the next error you’ll see is usually related to SELinux blocking legitimate operations, often reported in /var/log/audit/audit.log.