Cyber Intelligence
Users, Permissions and Access Control · Access control

L8. PAM: How Linux Handles Authentication

Video generating

Check back soon for the video lesson on PAM: How Linux Handles Authentication

Pluggable Authentication Modules (PAM) is the framework that controls how Linux verifies user identity, enforces password policies, and locks accounts after failed attempts. This lesson covers how PAM works, its configuration structure, and the modules most relevant to security administration.

What Is PAM?

PAM (Pluggable Authentication Modules) is a framework that separates authentication logic from the applications that need it. Instead of every program (login, SSH, sudo, su) implementing its own password checking, account lockout, and session setup, they all delegate to PAM. PAM then decides which authentication checks to perform based on its configuration files.

This design has two major security benefits:

  1. Centralized policy: You configure password strength rules, account lockout, and session limits in one place. Every PAM-aware application automatically enforces the same policies.
  2. Modular design: You can add, remove, or reorder authentication steps (password checks, two-factor authentication, biometrics) without modifying any application code.

How PAM Works

When a user tries to log in via SSH, the sshd process does not check the password itself. Instead, it calls PAM with the username and credentials. PAM then processes a stack of modules defined in the relevant configuration file. Each module performs one check and returns a result (success, failure, or other). PAM combines these results according to its rules and tells sshd whether to allow or deny the login.

The Four PAM Module Types

PAM organizes its modules into four categories, processed in this order:

TypePurposeExample
authVerify the user's identity (password, token, key)Check password against /etc/shadow
accountCheck if the account is allowed to log inVerify account is not expired or locked
passwordHandle password changesEnforce strength requirements when changing a password
sessionSet up and tear down the user's sessionCreate login records, set resource limits
Each type can have multiple modules stacked together. For example, the auth stack might first check a password, then check a two-factor token.

PAM Configuration Files

PAM configuration lives in the /etc/pam.d/ directory. Each file corresponds to a service (an application that uses PAM):

ls /etc/pam.d/

Typical files:

FileControls Authentication For
/etc/pam.d/sshdSSH logins
/etc/pam.d/loginConsole logins
/etc/pam.d/sudosudo commands
/etc/pam.d/suSwitching users with su
/etc/pam.d/common-authShared auth config included by other files (Debian/Ubuntu)
/etc/pam.d/system-authShared auth config (RHEL/CentOS)
/etc/pam.d/common-passwordShared password policy (Debian/Ubuntu)
/etc/pam.d/password-authShared password policy (RHEL/CentOS)

Configuration Line Format

Each line in a PAM file follows this structure:

type    control    module    [arguments]

Example from /etc/pam.d/common-auth:

auth    required    pam_unix.so    nullok
auth    optional    pam_permit.so

Control Values

The control field determines how PAM handles the module's result:

ControlBehavior
requiredMust succeed for overall success. If it fails, continue checking remaining modules but ultimately deny.
requisiteMust succeed. If it fails, immediately deny (do not continue the stack).
sufficientIf this succeeds and no prior required module failed, immediately allow.
optionalResult is only significant if it is the only module in the stack.
Security note: The difference between required and requisite matters. required continues processing even after failure (which prevents attackers from learning which specific check failed). requisite fails immediately (which can leak information but is faster).

Essential PAM Modules

pam_unix: Standard Password Authentication

This is the most fundamental module. It checks passwords against /etc/shadow.

auth    required    pam_unix.so

pam_pwquality: Password Strength Enforcement

pam_pwquality enforces password complexity rules when users set or change passwords:
# Install on Ubuntu if not present
sudo apt install libpam-pwquality

Configuration in /etc/pam.d/common-password (Ubuntu):

password    requisite    pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1
ParameterMeaning
minlen=12Minimum password length of 12 characters
difok=3At least 3 characters must differ from the old password
ucredit=-1At least 1 uppercase letter required
lcredit=-1At least 1 lowercase letter required
dcredit=-1At least 1 digit required
ocredit=-1At least 1 special character required
retry=3Allow 3 attempts before failing
You can also configure these settings in /etc/security/pwquality.conf:
sudo cat /etc/security/pwquality.conf

pam_faillock: Account Lockout After Failed Attempts

pam_faillock (which replaced the older pam_tally2) locks accounts after a configurable number of failed login attempts:

Configuration in /etc/pam.d/common-auth (Ubuntu) or /etc/pam.d/system-auth (RHEL):

auth    required    pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth    required    pam_unix.so
auth    required    pam_faillock.so authfail audit deny=5 unlock_time=900
ParameterMeaning
deny=5Lock the account after 5 failed attempts
unlock_time=900Automatically unlock after 900 seconds (15 minutes)
auditLog failed attempts to the system log
silentDo not reveal to the user that the account is locked (prevents enumeration)
Managing locked accounts:
# View failed login attempts for a user
faillock --user idan

# Unlock a locked account sudo faillock --user idan --reset

pam_limits: Resource Limits

pam_limits enforces resource limits defined in /etc/security/limits.conf:
# /etc/security/limits.conf
# Limit the number of simultaneous logins
*    hard    maxlogins    3

# Limit maximum number of open files * soft nofile 1024 * hard nofile 65536

# Limit process count (prevents fork bombs) * hard nproc 256

The nproc limit is a defense against fork bomb attacks (:(){ :|:& };:), which spawn processes recursively until the system runs out of resources.

Password Aging and Expiration

PAM works in conjunction with password aging settings stored in /etc/shadow and managed with the chage command:

# View password aging information for a user
sudo chage -l idan

# Set password to expire after 90 days sudo chage -M 90 idan

# Set minimum days between password changes (prevents rapid cycling) sudo chage -m 7 idan

# Set warning period (days before expiry to warn user) sudo chage -W 14 idan

# Force password change on next login sudo chage -d 0 idan

SettingRecommended ValuePurpose
Maximum age90 daysForce periodic password rotation
Minimum age7 daysPrevent users from immediately reverting to old password
Warning period14 daysGive users time to plan a change
Minimum length12+ charactersResist brute-force attacks
ComplexityMixed case, digits, special charsIncrease keyspace
HistoryRemember last 12 passwordsPrevent password reuse
Note: Modern guidance from NIST (SP 800-63B) recommends longer passwords over complex ones and discourages mandatory periodic rotation unless there is evidence of compromise. Your organization's compliance requirements may differ.

Putting It Together: A Hardened PAM Configuration

Here is what a security-focused PAM auth stack looks like conceptually:

  1. pam_faillock (preauth): Check if the account is already locked
  2. pam_unix: Verify the password against /etc/shadow
  3. pam_faillock (authfail): Record the failure if authentication failed
  4. pam_pwquality: Enforce password strength on changes
  5. pam_limits: Apply resource limits for the session

This layered approach ensures that every login attempt is checked against lockout policy, authenticated against the password store, and constrained by resource limits. Each module does one thing, and the stack combines them into a comprehensive authentication flow.

Common Mistakes to Avoid

  1. Editing PAM files without a backup: A misconfigured PAM stack can lock everyone out. Always keep a root shell open while testing changes.
  2. Using requisite for the password module: This reveals to attackers that the password check specifically failed (versus account lockout or other checks).
  3. Setting unlock_time=0: This means locked accounts never automatically unlock, which can cause denial-of-service if an attacker deliberately triggers lockouts.
  4. Forgetting the root account: Ensure root is either excluded from lockout policies or has an alternative recovery method (physical console access).

Exam Focus Points
  • PAM separates authentication logic from applications: SSH, sudo, login, and su all delegate to the same centralized PAM configuration.
  • The four PAM module types are auth (identity verification), account (access checks), password (credential changes), and session (setup/teardown).
  • The "required" control continues processing after failure (hiding which check failed), while "requisite" fails immediately (faster but leaks information).
  • pam_faillock replaces pam_tally2 for account lockout: configure deny count, unlock_time, and use the "silent" flag to prevent account enumeration.
  • pam_pwquality enforces password strength rules (length, complexity, similarity to old password) during password changes.
Knowledge Check

1. What is the primary advantage of PAM's centralized authentication design?

2. What is the difference between the "required" and "requisite" PAM control values?

3. Why should the pam_faillock "silent" parameter be enabled?