Skip to content

Linux Host Baseline & User Hardening: Mount Flags, PAM & Sudoers

Created: 2026-11-10 Updated: 2026-11-10

Management Summary: While network firewalls and intrusion prevention systems protect the external perimeter, the host baseline determines whether an adversary remains trapped inside an unprivileged sandbox after initial exploitation or escalates privileges to achieve total system compromise. Standard Linux installations deliver permissive temporary directories, legacy password hashing, and dozens of overprivileged SUID binaries. This guide establishes an uncompromising enterprise baseline: filesystem hardening via restrictive mount flags (nodev, nosuid, noexec), hardened authentication stacks via Pluggable Authentication Modules (PAM) with pam_faillock, pam_pwquality, and modern yescrypt hashing, strict sudoers governance eliminating GTFOBins breakout vectors, systematic SUID/SGID remediation, and shared memory and core dump isolation.

  • Filesystem & Mount Hardening


    Enterprise partitioning and restrictive mount options (noexec, nosuid, nodev) applied to /tmp, /var/tmp, and /dev/shm preventing payload execution.

  • PAM Deep Architecture


    The four management groups (auth, account, password, session), control flags, and deterministic evaluation flow in the Linux authentication subsystem.

  • Brute-Force Defense (pam_faillock)


    Automated account lockout after failed attempts, temporary isolation, status inspection, and administrative unlocking via the faillock CLI.

  • Password Quality & yescrypt


    Enforcing robust password complexity with pam_pwquality and migrating to memory-hard password hashing via yescrypt in /etc/login.defs.

  • User Governance & Root Lock


    Disabling interactive shells on service accounts (/usr/sbin/nologin), locking the interactive root password, and automated session timeouts (TMOUT).

  • Sudoers Hardening & Least Privilege


    Secure sudoers.d rule design, pseudo-terminal enforcement (use_pty), strict session timeouts, and mitigating privilege escalation via binaries (GTFOBins).


1. Filesystem Hardening & Secure Mount Options

Temporary directories such as /tmp, /var/tmp, and /dev/shm must be world-writable (chmod 1777) to allow unprivileged user accounts and system daemons to store transient files. This characteristic makes them the primary staging ground for attackers: following a successful exploit in a web application (e.g., arbitrary file upload or remote code execution), threat actors almost universally drop their exploit payloads into /tmp or /dev/shm to invoke secondary binaries.

The Three Defensive Mount Flags

To neutralize this attack vector at the kernel level, temporary mount points must enforce three restrictive mount options:

  • nodev: Prevents the kernel from interpreting character or block special devices located on this filesystem. Attackers cannot synthesize unprivileged raw disk devices.
  • nosuid: Causes the kernel to ignore Set-User-ID (SUID) and Set-Group-ID (SGID) bits. Binaries stored on these partitions cannot escalate privileges.
  • noexec: Forbids the direct execution of binaries and scripts on the filesystem. If an attacker attempts to run ./exploit, the kernel rejects the execve() system call with EACCES (Permission denied).

Hardened /etc/fstab Configuration

Edit /etc/fstab and secure temporary filesystems:

# /etc/fstab - Hardened mount configuration for enterprise servers

# Dedicated /tmp directory as tmpfs in memory (or separate partition)
tmpfs   /tmp        tmpfs   defaults,noexec,nosuid,nodev,size=2G,mode=1777   0 0

# Bind-mount /var/tmp to /tmp (prevents bypasses)
/tmp    /var/tmp    none    bind,defaults,noexec,nosuid,nodev                0 0

# Secure shared memory in RAM
tmpfs   /dev/shm    tmpfs   defaults,noexec,nosuid,nodev,size=1G,mode=1777   0 0

Apply the configuration immediately without rebooting:

# Remount temporary filesystems
sudo mount -o remount /tmp
sudo mount -o remount /dev/shm

System-Wide umask Hardening

The default user file-creation mask (umask 022) grants all system users world-readable permissions on newly created files (rwxr-xr-x). Production enterprise standards require umask 027 (Owner: full access, Group: read/execute, Others: no access).

Configure the system baseline in /etc/login.defs:

# /etc/login.defs
UMASK           027

Enforce the policy for all interactive shells via /etc/profile.d/umask.sh:

# /etc/profile.d/umask.sh
umask 027

2. Pluggable Authentication Modules (PAM) Deep Architecture

Every authentication request under Linux—whether local console logins, SSH, sudo, su, or desktop display managers—is processed through the PAM framework. PAM decouples applications from authentication methods by organizing operations into four distinct management stacks:

%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
    User_Request["User Request<br/>(Login / sudo / ssh)"] ==> PAM_Entry["PAM API Entrypoint<br/>(/etc/pam.d/<service>)"]
    PAM_Entry --> Stack_Auth["1. auth Stack<br/>(Identity Validation / Password)"]
    Stack_Auth --> Stack_Account["2. account Stack<br/>(Account Validity / Expiry)"]
    Stack_Account --> Stack_Password["3. password Stack<br/>(Password Updates / Complexity)"]
    Stack_Password --> Stack_Session["4. session Stack<br/>(Environment / Limits / Mounts)"]
    Stack_Session ==> Success["Access Granted<br/>(Shell / Process Spawned)"]

The Four Control Flags

Inside each stack, control flags determine how PAM processes the success or failure of individual modules:

  1. required: The module must succeed. If it fails, the overall authentication fails, but PAM continues evaluating subsequent modules in the stack to prevent timing analysis by adversaries.
  2. requisite: The module must succeed. If it fails, PAM immediately terminates the stack and returns failure.
  3. sufficient: If the module succeeds and no prior required module has failed, PAM immediately grants access without executing subsequent modules in the stack.
  4. optional: The module's return value is ignored unless it is the only module defined in the stack.

3. Brute-Force Defense with pam_faillock

Automated adversaries execute continuous dictionary attacks against open login interfaces. pam_faillock tracks failed authentication attempts and places affected accounts into temporary quarantine.

Configuration in /etc/security/faillock.conf

# /etc/security/faillock.conf
# Lock account after 5 consecutive failures
deny = 5

# Failure observation window: 15 minutes (900 seconds)
fail_interval = 900

# Lockout duration: 15 minutes (900 seconds)
unlock_time = 900

# Monitor root account for local authentication failures
even_deny_root

# Constrain root lockout to 5 minutes to prevent persistent denial of service
root_unlock_time = 300

# Log failed attempts to syslog
audit

# Directory storing failure tally files
dir = /var/run/faillock

Integration in /etc/pam.d/common-auth (Debian/Ubuntu)

Ensure pam_faillock wraps the primary auth stack:

# /etc/pam.d/common-auth
auth    required    pam_faillock.so preauth
auth    [success=1 default=ignore]  pam_unix.so nullok
auth    [default=die] pam_faillock.so authfail
auth    sufficient  pam_faillock.so authsucc

Administrative Operations with faillock

# Inspect recorded failures for a specific user
sudo faillock --user devuser

# Review all currently locked accounts
sudo faillock

# Manually unlock an account immediately
sudo faillock --user devuser --reset

4. Password Quality & Modern yescrypt Hashing

Weak passwords enable credential-stuffing breaches. Using pam_pwquality, we enforce cryptographically robust minimum entropy standards.

Configuration in /etc/security/pwquality.conf

# /etc/security/pwquality.conf
# Minimum required password length
minlen = 14

# Require at least 1 digit
dcredit = -1

# Require at least 1 uppercase letter
ucredit = -1

# Require at least 1 lowercase letter
lcredit = -1

# Require at least 1 special character
ocredit = -1

# Allow at most 3 consecutive identical characters
maxrepeat = 3

# Forbid strings matching username or GECOS fields
gecoscheck = 1

# Minimum required character changes relative to previous password
difok = 4

Migrating to Memory-Hard yescrypt Hashing

Traditional SHA-512 password hashes can be cracked on modern GPUs at rates exceeding billions of candidate hashes per second. yescrypt is a modern, memory-hard key derivation function (KDF) that requires substantial RAM allocation per hashing iteration, rendering GPU cracking attacks economically impractical.

Configure yescrypt in /etc/login.defs:

# /etc/login.defs
ENCRYPT_METHOD YESCRYPT
YESCRYPT_COST_FACTOR 5

5. User Governance: Root Lock & Inactive Accounts

Servers burdened with unmonitored default accounts present unnecessary attack surface.

1. Locking the Root Account Password

On a hardened system, interactive root logins are completely disabled. Administrative tasks are mediated strictly through sudo:

# Lock root account password (prepends '!' to hash in /etc/shadow)
sudo passwd -l root

2. Disabling Shells on System Accounts

System accounts (such as daemon, bin, sys, games) must never possess interactive login shells. Audit /etc/passwd:

# Identify service accounts (UID < 1000) configured with valid shells
awk -F: '($3 < 1000 && $1 != "root" && $7 !~ /(nologin|false)/) {print $1, $7}' /etc/passwd

# Immediately assign /usr/sbin/nologin to service accounts
sudo usermod -s /usr/sbin/nologin <accountname>

3. Automated Inactivity Timeouts

Idle terminal sessions on unattended workstations or jump hosts present an immediate risk. Enforce an automated 15-minute logout policy via /etc/profile.d/autologout.sh:

# /etc/profile.d/autologout.sh
# 900 seconds = 15 minute inactivity timeout
TMOUT=900
readonly TMOUT
export TMOUT

6. Sudoers Hardening & GTFOBins Mitigation

The sudo utility governs administrative privilege escalation. A permissive sudoers configuration negates all other host hardening controls.

The Golden Rule: Forbid ALL=(ALL) NOPASSWD: ALL

Never configure passwordless sudo globally. Always modify sudoers rules using visudo:

# Safely edit dedicated sudoers drop-in configuration
sudo visudo -f /etc/sudoers.d/enterprise-hardening

Apply these production directives:

# /etc/sudoers.d/enterprise-hardening

# Reset environment variables upon command execution
Defaults    env_reset

# Enforce secure, non-user-manipulable PATH
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Allocate dedicated pseudo-terminal (prevents TTY hijacking via TIOCSTI)
Defaults    use_pty

# Maintain a dedicated audit log of all executed sudo commands
Defaults    logfile="/var/log/sudo.log"

# Restrict password credential cache timeout to 5 minutes
Defaults    timestamp_timeout=5

# Grant administrative access only to the sudo/wheel group
%sudo   ALL=(ALL:ALL) ALL

GTFOBins Warning: Never Grant Sudo to Text Editors or Interpreters

Never permit unprivileged users to execute binaries such as vi, vim, nano, less, more, awk, find, python, or bash with sudo permissions!

Nearly all standard UNIX utilities feature shell escapes. A user authorized to run sudo vi /etc/hosts can execute :!/bin/bash from inside the editor, instantly spawning an interactive root shell (thoroughly cataloged on GTFOBins).


7. SUID/SGID Remediation & Core Dump Isolation

The Set-User-ID (SUID) bit (4000 octal) causes an executable to execute under the permissions of the file owner (root) rather than the calling user.

Auditing SUID/SGID Binaries

Locate all active SUID and SGID executables across the filesystem:

# Search for SUID (4000) and SGID (2000) binaries
sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -exec ls -ld {} +

Many utilities shipped on general-purpose distributions are unnecessary on headless enterprise servers. Strip unneeded SUID bits:

# Remove SUID permissions from superfluous utilities
sudo chmod u-s /usr/bin/chsh
sudo chmod u-s /usr/bin/chfn
sudo chmod u-s /usr/bin/mount
sudo chmod u-s /usr/bin/umount

Disabling Core Dumps

When an unhandled crash occurs, the kernel dumps process memory (core dump) to disk. If the crashed process handled passwords, private SSH keys, or database credentials, local adversaries can extract secrets from the dump file.

Disable core dumps system-wide in /etc/security/limits.conf:

# /etc/security/limits.conf
*       hard    core    0
*       soft    core    0

Enforce kernel-level restrictions via sysctl:

# Forbid core dumps from processes with changed UID/GID
echo "fs.suid_dumpable = 0" | sudo tee /etc/sysctl.d/50-coredump.conf
sudo sysctl -p /etc/sysctl.d/50-coredump.conf

8. Enterprise Verification Checklist

Domain Audit Command Expected Compliant State
Mounts mount \| grep -E "(tmp\|shm)" noexec,nosuid,nodev enforced
Umask umask Returns 0027
Faillock faillock Displays active failure tallies
Root Lock passwd -S root Returns L (Locked)
Sudo Log tail -n 20 /var/log/sudo.log Records commands with timestamps
SUID Audit find / -xdev -perm -4000 -type f Minimal set only (sudo, passwd)

With this host baseline established, local privilege escalation vectors are neutralized, authentication is hardened, and temporary filesystems are insulated against executable malware payloads.