You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/linux-hardening/linux-post-exploitation/pam-pluggable-authentication-modules.md
+44-5Lines changed: 44 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,6 +44,16 @@ Controls dictate the module's response to success or failure, influencing the ov
44
44
-**Sufficient**: Success bypasses the rest of the same realm's checks unless a subsequent module fails.
45
45
-**Optional**: Only causes failure if it's the sole module in the stack.
46
46
47
+
#### Offensive Semantics That Matter
48
+
49
+
When backdooring PAM, the **location of the inserted rule** is often more important than the payload itself:
50
+
51
+
-`include` and `substack` pull rules from other files, so editing `sshd` might only affect SSH while editing `system-auth`, `common-auth`, or another shared stack affects several services at once.
52
+
- PAM also supports bracketed controls such as `[success=1 default=ignore]`. These can be abused to **skip one or more modules** after a successful custom check instead of visibly replacing `pam_unix.so`.
53
+
- The `module-path` can be **absolute** (`/usr/lib/security/pam_custom.so`) or **relative** to the default PAM module directory. On modern Linux systems the real directories are often `/lib/security`, `/lib64/security`, `/usr/lib/security`, or multiarch paths like `/usr/lib/x86_64-linux-gnu/security`.
54
+
55
+
Quick operator takeaway: always map the **full service graph** before patching. For example, `sshd -> password-auth -> system-auth` on some distros or `sshd -> system-remote-login -> system-login -> system-auth` on others means the same one-line implant may fan out much wider than intended.
56
+
47
57
#### Example Scenario
48
58
49
59
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.
Instead of replacing `pam_unix.so`, a lighter touch is to append a `pam_exec` line in `/etc/pam.d/sshd` so every SSH login launches an implant while leaving the normal stack intact:
`pam_exec` runs as root inside the sshd PAM context, so the script can drop reverse shells, collect env vars, or re-open implanted sockets with no filesystem changes to core libraries.
148
+
`pam_exec` receives PAM metadata in environment variables such as `PAM_USER`, `PAM_RHOST`, `PAM_SERVICE`, `PAM_TTY`, and `PAM_TYPE`. With `expose_authtok`, the helper can also read the password from `stdin` during `auth` or `password` phases. If you want the helper to run with the effective UID instead of the real UID, add `seteuid`.
149
+
150
+
Practical notes:
151
+
152
+
-`session optional pam_exec.so ...` is better for **post-login actions** such as re-opening sockets or spawning a detached daemon.
153
+
-`auth optional pam_exec.so quiet expose_authtok ...` is the usual choice for **credential capture** because it runs before the session opens.
154
+
-`type=session` or `type=auth` can be used to constrain execution to a specific PAM phase and avoid noisy double execution.
155
+
156
+
### Surviving distro tooling: `authselect`
157
+
158
+
On RHEL, CentOS Stream, Fedora, and derivative systems, direct edits to generated files such as `/etc/pam.d/system-auth` or `/etc/pam.d/password-auth` may be **overwritten by `authselect`**. For persistence, operators often patch the active custom profile under `/etc/authselect/custom/<profile>/` and then re-select or apply it.
159
+
160
+
Typical workflow when you have root:
161
+
162
+
```bash
163
+
# Inspect the active profile first
164
+
authselect current
165
+
166
+
# If a custom profile already exists, edit its PAM templates instead of system-auth directly
# Re-apply the profile after modifying the template files
170
+
authselect selectcustom/<profile>
171
+
```
172
+
173
+
This matters forboth offense and triage: if `/etc/pam.d/system-auth` contains the banner `Generated by authselect` and `Do not modify this file manually`, then the real persistence point may live under `/etc/authselect/custom/` rather thanin`/etc/pam.d/`.
174
+
175
+
### Recent tradecraft seen in the wild
176
+
177
+
Recent 2025 reporting on the **Plague** Linux backdoor showed the same core idea taken further: a malicious PAM component with a **static bypass password**, plus cleanup of SSH-related environment variables and shell history (`HISTFILE=/dev/null`) to reduce session traces after login. That is a useful hunting pattern because the backdoor logic may live in PAM while the stealth artifacts only appear **after** authentication succeeds.
- [Nextron Systems - Plague: A Newly Discovered PAM-Based Backdoor for Linux](https://www.nextron-systems.com/2025/08/01/plague-a-newly-discovered-pam-based-backdoor-for-linux/)
0 commit comments