
Proof-of-Concept-Exploit für CVE-2025-49132, das eine nicht authentifizierte Remote-Codeausführung im Pterodactyl Panel <= 1.11.10 über die Injektion des Locale-Parameters ermöglicht. Enthält Prüf- und Exploit-Modi.
Proof-of-Concept für CVE-2025-49132 zur Remote Code Execution im Pterodactyl Panel <= 1.11.10
Dieses PoC bezieht sich auf Referenzen aus
# 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>
Analysiert man den git diff der Datei LocaleController.php zwischen v1.11.10 und v1.11.11 (Link), erkennt man, dass der Controller die Parameter locale und namespace ohne Validierung oder Bereinigung entgegennimmt.
Um zu verstehen, warum dies gefährlich ist, schauen wir uns das in panel/routes/base.php konfigurierte Routing an. Die Route entfernt explizit die Authentifizierungs-Middleware, sodass nicht authentifizierte Benutzer /locales/locale.json aufrufen und die erforderlichen Query-Parameter wie locale und namespace angeben können. Das bedeutet, dass diese Parameter nun vom Benutzer kontrolliert werden.
Route::get('/locales/locale.json', Base\LocaleController::class)
// Remove authentication middleware for this endpoint
->withoutMiddleware(['auth', RequireTwoFactorAuthentication::class]);
Kehren wir zu LocalController.php zurück. Die folgende Codezeile liefert die RCE-Magie.
$this->loader->load($locale, str_replace('.', '/', $namespace))
Die Funktion load stammt aus dem Übersetzungsframework von Laravel (hier):
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);
}
load drei Argumente akzeptiert. Auch wenn es zunächst verwirrend ist, wird der Wert str_replace('.', '/', $namespace) tatsächlich an das zweite Argument $group übergeben.$namespace nie * sein wird, da es immer NULL ist. Ebenso wird $group nie * sein, da wir kontrollieren können, was hier übergeben wird.$namespace null ist, der Zweig ausgeführt, was zur Ausführung von loadPaths in #4 führt.Nachdem wir das oben Genannte verstanden haben, wenden wir uns der Analyse von loadPaths zu, wo die eigentliche Magie passiert.
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;
}, []);
}
.php anhängt.getRequire() geladen, was die PHP-Datei ausführt und deren Array zurückgibt.Da wir den URL-Parameter namespace kontrollieren, können wir beeinflussen, welche Datei die Anwendung zu laden versucht. Indem wir einen Wert angeben, der auf ein .php-Skript verweist, können wir den Server dazu bringen, dieses Skript auszuführen. Um beispielsweise phpinfo.php zu laden, können wir den Parameter wie folgt setzen: namespace=phpinfo
Das PoC versucht, über die pearcmd.php beliebige Dateien zu schreiben. Diese Methode wurde bereits in vielen ähnlichen PoCs und in der Sicherheitsforschung verwendet.
Beachte, dass sich pearcmd.php in verschiedenen Verzeichnissen befinden kann, z. B.
/usr/share/php/pearcmd.php/usr/share/php/PEAR/pearcmd.php/usr/lib/php/pearcmd.phpund vielen weiteren.
Die geschriebene Datei enthält den typischen schädlichen PHP-Code.
Nur für autorisierte Tests gedacht. Nicht auf Systemen verwenden, die dir nicht gehören oder für die du keine ausdrückliche Testgenehmigung hast.
Du bist für die Einhaltung aller geltenden Gesetze verantwortlich; die Autoren übernehmen keinerlei Haftung für Missbrauch.
Die Python-Bibliothek requests ist ein wenig zu hilfreich, da sie Zeichen in der angegebenen URL kodiert. Ich habe lange Zeit versucht, dieses Problem zu lösen, und habe schließlich einfach curl direkt verwendet. Ich wäre dankbar, wenn jemand bei diesem Problem helfen könnte.