Deserialization
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Serialization wird als die Methode verstanden, ein Objekt in ein Format zu konvertieren, das gespeichert werden kann, mit der Absicht, das Objekt entweder zu speichern oder es als Teil eines Kommunikationsprozesses zu übertragen. Diese Technik wird häufig eingesetzt, um sicherzustellen, dass das Objekt zu einem späteren Zeitpunkt rekonstruiert werden kann, wobei seine Struktur und sein Zustand beibehalten werden.
Deserialization hingegen ist der Prozess, der der Serialisierung entgegenwirkt. Es beinhaltet das Entnehmen von Daten, die in einem bestimmten Format strukturiert sind, und deren Rekonstruktion zurück in ein Objekt.
Deserialization kann gefährlich sein, da sie potenziell Angreifern ermöglicht, die serialisierten Daten zu manipulieren, um schädlichen Code auszuführen oder unerwartetes Verhalten in der Anwendung während des Rekonstruktionsprozesses des Objekts zu verursachen.
In PHP werden spezifische magische Methoden während der Serialisierungs- und Deserialisierungsprozesse verwendet:
__sleep
: Wird aufgerufen, wenn ein Objekt serialisiert wird. Diese Methode sollte ein Array der Namen aller Eigenschaften des Objekts zurückgeben, die serialisiert werden sollen. Sie wird häufig verwendet, um ausstehende Daten zu speichern oder ähnliche Aufräumarbeiten durchzuführen.
__wakeup
: Wird aufgerufen, wenn ein Objekt deserialisiert wird. Sie wird verwendet, um alle Datenbankverbindungen, die während der Serialisierung verloren gegangen sein könnten, wiederherzustellen und andere Reinitialisierungsaufgaben durchzuführen.
__unserialize
: Diese Methode wird anstelle von __wakeup
(sofern sie existiert) aufgerufen, wenn ein Objekt deserialisiert wird. Sie bietet mehr Kontrolle über den Deserialisierungsprozess im Vergleich zu __wakeup
.
__destruct
: Diese Methode wird aufgerufen, wenn ein Objekt kurz davor steht, zerstört zu werden, oder wenn das Skript endet. Sie wird typischerweise für Aufräumarbeiten verwendet, wie das Schließen von Datei-Handles oder Datenbankverbindungen.
__toString
: Diese Methode ermöglicht es, ein Objekt als String zu behandeln. Sie kann verwendet werden, um eine Datei zu lesen oder andere Aufgaben basierend auf den Funktionsaufrufen innerhalb des Objekts durchzuführen, wodurch eine textuelle Darstellung des Objekts bereitgestellt wird.
Wenn Sie sich die Ergebnisse ansehen, können Sie sehen, dass die Funktionen __wakeup
und __destruct
aufgerufen werden, wenn das Objekt deserialisiert wird. Beachten Sie, dass in mehreren Tutorials zu finden ist, dass die Funktion __toString
aufgerufen wird, wenn versucht wird, ein Attribut auszugeben, aber anscheinend passiert das nicht mehr.
Die Methode __unserialize(array $data)
wird anstatt von __wakeup()
aufgerufen, wenn sie in der Klasse implementiert ist. Sie ermöglicht es Ihnen, das Objekt zu deserialisieren, indem Sie die serialisierten Daten als Array bereitstellen. Sie können diese Methode verwenden, um Eigenschaften zu deserialisieren und alle erforderlichen Aufgaben bei der Deserialisierung auszuführen.
Sie können ein erklärtes PHP-Beispiel hier lesen: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hier https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf oder hier https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
Sie könnten die PHP-Autoload-Funktionalität missbrauchen, um beliebige PHP-Dateien und mehr zu laden:
PHP - Deserialization + Autoload ClassesWenn Sie aus irgendeinem Grund einen Wert als Referenz zu einem anderen serialisierten Wert serialisieren möchten, können Sie:
PHPGGC kann Ihnen helfen, Payloads zu generieren, um PHP-Deserialisierungen auszunutzen.
Beachten Sie, dass Sie in mehreren Fällen keinen Weg finden werden, um eine Deserialisierung im Quellcode der Anwendung auszunutzen, aber Sie möglicherweise den Code externer PHP-Erweiterungen ausnutzen können.
Wenn möglich, überprüfen Sie die phpinfo()
des Servers und suchen Sie im Internet (sogar in den Gadgets von PHPGGC) nach möglichen Gadgets, die Sie ausnutzen könnten.
Wenn Sie eine LFI gefunden haben, die nur die Datei liest und den PHP-Code darin nicht ausführt, zum Beispiel mit Funktionen wie file_get_contents(), fopen(), file() oder file_exists(), md5_file(), filemtime() oder filesize(). Sie können versuchen, eine Deserialisierung auszunutzen, die auftritt, wenn eine Datei mit dem phar-Protokoll gelesen wird. Für weitere Informationen lesen Sie den folgenden Beitrag:
phar:// deserializationWenn das Objekt unpickled wird, wird die Funktion __reduce__ ausgeführt. Bei einer Ausnutzung könnte der Server einen Fehler zurückgeben.
Bevor Sie die Bypass-Technik überprüfen, versuchen Sie, print(base64.b64encode(pickle.dumps(P(),2)))
zu verwenden, um ein Objekt zu generieren, das mit Python2 kompatibel ist, wenn Sie Python3 ausführen.
Für weitere Informationen über das Entkommen aus pickle jails siehe:
Bypass Python sandboxesDie folgende Seite präsentiert die Technik, um eine unsichere Deserialisierung in YAMLs Python-Bibliotheken zu missbrauchen und endet mit einem Tool, das verwendet werden kann, um RCE-Deserialisierungs-Payloads für Pickle, PyYAML, jsonpickle und ruamel.yaml zu generieren:
Python Yaml DeserializationJS hat keine "magischen" Funktionen wie PHP oder Python, die nur zum Erstellen eines Objekts ausgeführt werden. Aber es gibt einige Funktionen, die häufig verwendet werden, auch ohne sie direkt aufzurufen, wie toString
, valueOf
, toJSON
.
Wenn Sie eine Deserialisierung missbrauchen, können Sie diese Funktionen kompromittieren, um anderen Code auszuführen (potenziell durch Missbrauch von Prototyp-Verschmutzungen), könnten Sie beliebigen Code ausführen, wenn sie aufgerufen werden.
Eine weitere "magische" Möglichkeit, eine Funktion aufzurufen, ohne sie direkt aufzurufen, besteht darin, ein Objekt zu kompromittieren, das von einer asynchronen Funktion zurückgegeben wird (Versprechen). Denn wenn Sie das Rückgabeobjekt in ein anderes Versprechen mit einer Eigenschaft namens "then" vom Typ Funktion umwandeln, wird es ausgeführt, nur weil es von einem anderen Versprechen zurückgegeben wird. Folgen Sie diesem Link für weitere Informationen.
__proto__
und prototype
VerschmutzungWenn Sie mehr über diese Technik erfahren möchten, sehen Sie sich das folgende Tutorial an:
NodeJS - __proto__ & prototype PollutionDiese Bibliothek ermöglicht es, Funktionen zu serialisieren. Beispiel:
Das serialisierte Objekt wird wie folgt aussehen:
Sie können im Beispiel sehen, dass, wenn eine Funktion serialisiert wird, das _$$ND_FUNC$$_
-Flag an das serialisierte Objekt angehängt wird.
Innerhalb der Datei node-serialize/lib/serialize.js
finden Sie dasselbe Flag und wie der Code es verwendet.
Wie Sie im letzten Codeabschnitt sehen können, wenn das Flag gefunden wird, wird eval
verwendet, um die Funktion zu deserialisieren, also wird im Grunde Benutzereingabe innerhalb der eval
-Funktion verwendet.
Allerdings führt das bloße Serialisieren einer Funktion nicht zu ihrer Ausführung, da es notwendig wäre, dass ein Teil des Codes y.rce
aufruft in unserem Beispiel, und das ist höchst unwahrscheinlich.
Dennoch könnten Sie einfach das serialisierte Objekt modifizieren, indem Sie einige Klammern hinzufügen, um die serialisierte Funktion automatisch auszuführen, wenn das Objekt deserialisiert wird.
Im nächsten Codeabschnitt beachten Sie die letzte Klammer und wie die unserialize
-Funktion den Code automatisch ausführen wird:
Wie zuvor angegeben, wird diese Bibliothek den Code nach _$$ND_FUNC$$_
erhalten und ihn ausführen mit eval
. Daher können Sie, um Code automatisch auszuführen, den Teil zur Funktions Erstellung und die letzte Klammer löschen und einfach eine JS-Einzeiler wie im folgenden Beispiel ausführen:
Sie können hier weitere Informationen über die Ausnutzung dieser Schwachstelle finden.
Ein bemerkenswerter Aspekt von funcster ist die Unzugänglichkeit von Standard-Built-in-Objekten; sie fallen außerhalb des zugänglichen Bereichs. Diese Einschränkung verhindert die Ausführung von Code, der versucht, Methoden auf Built-in-Objekten aufzurufen, was zu Ausnahmen wie "ReferenceError: console is not defined"
führt, wenn Befehle wie console.log()
oder require(something)
verwendet werden.
Trotz dieser Einschränkung ist die Wiederherstellung des vollständigen Zugriffs auf den globalen Kontext, einschließlich aller Standard-Built-in-Objekte, durch einen bestimmten Ansatz möglich. Durch die direkte Nutzung des globalen Kontexts kann man diese Einschränkung umgehen. Zum Beispiel kann der Zugriff mit dem folgenden Snippet wiederhergestellt werden:
Für weitere Informationen lesen Sie diese Quelle.
Das serialize-javascript-Paket ist ausschließlich für Serialisierungszwecke konzipiert und verfügt über keine integrierten Deserialisierungsfunktionen. Die Benutzer sind dafür verantwortlich, ihre eigene Methode zur Deserialisierung zu implementieren. Eine direkte Verwendung von eval
wird im offiziellen Beispiel zur Deserialisierung von serialisierten Daten vorgeschlagen:
Wenn diese Funktion verwendet wird, um Objekte zu deserialisieren, können Sie es leicht ausnutzen:
Für weitere Informationen lesen Sie diese Quelle.
In den folgenden Seiten finden Sie Informationen darüber, wie Sie diese Bibliothek missbrauchen können, um beliebige Befehle auszuführen: