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:
- Centralized policy: You configure password strength rules, account lockout, and session limits in one place. Every PAM-aware application automatically enforces the same policies.
- 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:
| Type | Purpose | Example |
|---|---|---|
| auth | Verify the user's identity (password, token, key) | Check password against /etc/shadow |
| account | Check if the account is allowed to log in | Verify account is not expired or locked |
| password | Handle password changes | Enforce strength requirements when changing a password |
| session | Set up and tear down the user's session | Create login records, set resource limits |
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:
| File | Controls Authentication For |
|---|---|
/etc/pam.d/sshd | SSH logins |
/etc/pam.d/login | Console logins |
/etc/pam.d/sudo | sudo commands |
/etc/pam.d/su | Switching users with su |
/etc/pam.d/common-auth | Shared auth config included by other files (Debian/Ubuntu) |
/etc/pam.d/system-auth | Shared auth config (RHEL/CentOS) |
/etc/pam.d/common-password | Shared password policy (Debian/Ubuntu) |
/etc/pam.d/password-auth | Shared 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:
| Control | Behavior |
|---|---|
required | Must succeed for overall success. If it fails, continue checking remaining modules but ultimately deny. |
requisite | Must succeed. If it fails, immediately deny (do not continue the stack). |
sufficient | If this succeeds and no prior required module failed, immediately allow. |
optional | Result is only significant if it is the only module in the stack. |
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-pwqualityConfiguration 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
| Parameter | Meaning |
|---|---|
minlen=12 | Minimum password length of 12 characters |
difok=3 | At least 3 characters must differ from the old password |
ucredit=-1 | At least 1 uppercase letter required |
lcredit=-1 | At least 1 lowercase letter required |
dcredit=-1 | At least 1 digit required |
ocredit=-1 | At least 1 special character required |
retry=3 | Allow 3 attempts before failing |
/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
| Parameter | Meaning |
|---|---|
deny=5 | Lock the account after 5 failed attempts |
unlock_time=900 | Automatically unlock after 900 seconds (15 minutes) |
audit | Log failed attempts to the system log |
silent | Do not reveal to the user that the account is locked (prevents enumeration) |
# 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
Recommended Password Policy Settings
| Setting | Recommended Value | Purpose |
|---|---|---|
| Maximum age | 90 days | Force periodic password rotation |
| Minimum age | 7 days | Prevent users from immediately reverting to old password |
| Warning period | 14 days | Give users time to plan a change |
| Minimum length | 12+ characters | Resist brute-force attacks |
| Complexity | Mixed case, digits, special chars | Increase keyspace |
| History | Remember last 12 passwords | Prevent password reuse |
Putting It Together: A Hardened PAM Configuration
Here is what a security-focused PAM auth stack looks like conceptually:
- pam_faillock (preauth): Check if the account is already locked
- pam_unix: Verify the password against /etc/shadow
- pam_faillock (authfail): Record the failure if authentication failed
- pam_pwquality: Enforce password strength on changes
- 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
- Editing PAM files without a backup: A misconfigured PAM stack can lock everyone out. Always keep a root shell open while testing changes.
- Using
requisitefor the password module: This reveals to attackers that the password check specifically failed (versus account lockout or other checks). - Setting
unlock_time=0: This means locked accounts never automatically unlock, which can cause denial-of-service if an attacker deliberately triggers lockouts. - Forgetting the root account: Ensure root is either excluded from lockout policies or has an alternative recovery method (physical console access).
- ✓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.
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?