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 root user 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/nologin or 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 PermitRootLogin setting in /etc/ssh/sshd_config:

    grep PermitRootLogin /etc/ssh/sshd_config
    

    Why it works: If it’s set to yes or prohibit-password (and you’re relying on passwords), it’s a risk.

  • Check PasswordAuthentication setting:

    grep PasswordAuthentication /etc/ssh/sshd_config
    

    Why it works: If it’s yes, your server is vulnerable to password guessing.

  • Check Protocol setting:

    grep Protocol /etc/ssh/sshd_config
    

    Why 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_config for lines like Ciphers, 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_config
    

    Why it works: Prevents direct root logins, forcing users to log in as a regular user and su or sudo to 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_config
    

    Why 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_config
    

    Why it works: Enforces the use of the secure SSHv2 protocol.

  • Restart SSH service:

    systemctl restart sshd
    

    Why 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/shadow
    

    Why it works: Should be owned by root:shadow and have permissions 0640 or 0644.

  • Check permissions on /etc/sudoers and /etc/sudoers.d/*:

    ls -l /etc/sudoers /etc/sudoers.d/
    

    Why it works: Should be owned by root:root and have permissions 0440.

  • 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/null
    

    Why 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/shadow
    

    Why 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/sudoers
    

    Why 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/file
    

    Why 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 -tulnp
    

    Why 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 -tulnp output 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 firewalld or iptables accordingly.

    firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="80" protocol="tcp" accept'
    firewall-cmd --reload
    

    Why 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 auditd is running:

    systemctl status auditd
    

    Why 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/*.rules
    

    Why it works: This is the configuration that dictates what is logged. A minimal configuration is a security risk.

Fixes:

  • Ensure auditd is enabled and running:

    systemctl enable auditd
    systemctl start auditd
    

    Why 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.

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.

Want structured learning?

Take the full Cdk course →