Heim  >  Artikel  >  Backend-Entwicklung  >  Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

藏色散人
藏色散人nach vorne
2019-04-02 12:00:003473Durchsuche

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Vorwort

Während ich PHP lernte, stellte ich fest, dass einige PHP-Funktionen schwer zu verstehen sind, wie z wie etwa PHP 00-Kürzung, MD5-Fehler, Deserialisierungsumgehung __wakeup und mehr. Ich möchte mich nicht auf das oberflächliche Verständnis beschränken, sondern untersuchen, wie der PHP-Kern das macht.

Das Folgende ist eine Deserialisierungsschwachstelle, die häufig in CTF verwendet wird, CVE-2016-7124 (unter Umgehung der magischen Funktion __wakeup), als Beispiel, um den Prozess des Debuggens des PHP-Kernels zu teilen. Einschließlich des gesamten Teils von der Einrichtung der Kernel-Quellcode-Debugging-Umgebung über die Serialisierung und Deserialisierung des Kernel-Quellcodes bis hin zur endgültigen Schwachstellenanalyse. (Empfohlen: PHP-Tutorial)

1. Gedanken, die durch ein Beispiel ausgelöst werden

Wir können uns zunächst das kleine Beispiel ansehen, das ich geschrieben habe.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Basierend auf dem Bild oben stellen wir zunächst die magischen Funktionen in PHP vor:

Werfen wir zunächst einen Blick auf die offizielle Dokumentation für mehrere häufig verwendete magische Funktionen. Einführung:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Um es hier zusammenzufassen: __construct wird aufgerufen, wenn eine Klasse als Instanz initialisiert wird, und __destruct wird aufgerufen, wenn sie initialisiert wird wird zerstört.

Wenn eine Klasse serialize zur Serialisierung aufruft, wird die Funktion __sleep automatisch aufgerufen. Wenn eine Zeichenfolge mit unserialize in eine Klasse deserialisiert werden soll, wird die Funktion __wakeup aufgerufen . Die oben genannten magischen Funktionen werden automatisch aufgerufen, sofern sie vorhanden sind. Sie müssen keine manuellen Display-Aufrufe durchführen.

Schauen wir uns nun den ersten Teil des Codes an. In der Funktion __destruct gibt es sensible Vorgänge zum Schreiben von Dateien. Wir verwenden hier Deserialisierung, um gefährliche Zeichenfolgen zu erstellen, die zu Schwachstellen bei der Codeausführung führen können.

Als wir die entsprechende Zeichenfolge erstellten und uns auf deren Verwendung vorbereiteten, stellten wir fest, dass in ihrer __wakeup-Funktion ein Filtervorgang vorhanden war, der unsere Konstruktion behinderte. Weil wir wissen, dass die Deserialisierung zuerst die Funktion __wakeup aufrufen muss.

Hier kommen wir nicht umhin, über die Verwendung dieser PHP-Deserialisierungsschwachstelle CVE-2016-7124 (Umgehung der magischen Funktion __wakeup) nachzudenken, um die magische Funktion ___wakeup, die während der Deserialisierung automatisch aufgerufen wird, einfach zu umgehen Operationen werden in die Datei geschrieben.

Natürlich ist der obige Code nur ein einfaches Beispiel, das ich persönlich gegeben habe, und in realen Situationen gibt es viele ähnliche Situationen wie oben. Aber diese Bypass-Methode fasziniert mich sehr. Wie wirkt sich der interne Betrieb und die Verarbeitung von PHP auf die Codelogik der oberen Ebene aus, um eine solche magische Situation (BUG) zu verursachen? Als nächstes werde ich eine dynamische Debugging-Analyse des PHP-Kernels durchführen. Erkunden Sie diese Frage.

Diese Schwachstelle (CVE-2016-7124) betrifft Versionen der PHP5-Serie vor 5.6.25 und der 7.x-Serie vor 7.0.10. Daher werden wir später zwei Versionen kompilieren: Eine ist Version 7.3.0, die von dieser Sicherheitslücke nicht betroffen ist, und die andere Version ist Version 5.6.10, in der die Sicherheitslücke besteht. Vergleichen Sie die beiden Versionen, um mehr über die Unterschiede zu erfahren.

2. Aufbau einer PHP-Quellcode-Debugging-Umgebung

Wir alle wissen, dass PHP in der Sprache C entwickelt wird, weil die Umgebung, die ich verwende, es ist WIN 10. Daher stellen wir hauptsächlich den Umgebungsaufbau unter Windows vor. Wir benötigen die folgenden Materialien:

PHP源码
PHP SDK工具包,用于构建PHP
调试所需要IDE

Der Quellcode kann auf GITHUB heruntergeladen werden, Link: https://github.com/php/php-src, Sie können die gewünschte Version zum Herunterladen auswählen.

Download-Adresse des PHPSDK-Toolkits: https://github.com/Microsoft/php-sdk-binary-tools Das von dieser Adresse heruntergeladene Toolkit unterstützt nur VC14 und VC15. Natürlich finden Sie auch VC11, VC12 usw., die niedrigere Versionen von PHP unterstützen, unter https://windows.php.net/downloads/. Bevor Sie das PHP SDK verwenden, müssen Sie sicherstellen, dass Sie VS mit den entsprechenden installiert haben Version der Windows SDK-Komponente.

Im folgenden Artikel werden PHP7.3.0 und 5.6.10 verwendet. Die Quellcodekompilierung dieser beiden Versionen wird im Folgenden vorgestellt. Die Methoden für andere Versionen sind ähnlich.

2.1 Kompilieren von Windows PHP 7.3.0

Native Umgebung WIN10 X64, PHP SDK wird über den obigen Github-Link heruntergeladen. Gehen Sie in das SDK-Verzeichnis und suchen Sie nach 4 Batchdateien. Doppelklicken Sie hier auf phpsdk-vc15-x64.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Geben Sie dann phpsdk_buildtreephp7 in diese Shell ein. Sie werden feststellen, dass der PHP7-Ordner im selben Verzeichnis angezeigt wird und sich auch das Shell-Verzeichnis geändert hat.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Dann legen wir den dekomprimierten Quellcode unter php7vc15x64, Shell in diesem Ordner ab und verwenden den Befehl phpsdk_deps–update–branchmaster, um die relevanten abhängigen Komponenten zu aktualisieren und herunterzuladen.

Nachdem Sie auf den Abschluss gewartet haben, geben Sie das Quellcodeverzeichnis ein und doppelklicken Sie auf die buildconf.bat Batchdatei. Dadurch werden die beiden Dateien configure.bat und configure.js freigegeben. cli– in der Shell konfiguriert die entsprechenden Kompilierungsoptionen. Wenn Sie andere Anforderungen haben, können Sie configure –help ausführen, um

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

zu sehen Verwenden Sie nach den Eingabeaufforderungen nmake, um direkt zu kompilieren.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Die Kompilierung ist abgeschlossen und das Verzeichnis der ausführbaren Dateien befindet sich im Ordner php7vc15x64php-srcx64Debug_TS. Wir können php -v eingeben, um relevante Informationen anzuzeigen.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

2.2 Kompilieren Sie Windows PHP 5.6.10

Die Methode ist die gleiche wie bei 7.3.0, beachten Sie jedoch, dass PHP5.6 verwendet Die WindowsSDK-Komponentenversion ist VC11. Sie müssen VS2012 herunterladen und können das von Github heruntergeladene PHP SDK nicht zum Kompilieren verwenden. Sie müssen das VC11 PHP SDK und die zugehörigen abhängigen Komponenten auf https://windows.php.net/ auswählen. Downloads/ zum Kompilieren. Der Rest ist genau das gleiche wie oben und wird hier nicht wiederholt.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

2.3 Debugging-Konfiguration

Da wir oben den PHP-Interpreter kompiliert haben, verwenden wir hier VSCODE direkt zum Debuggen.

Installieren Sie die C/C++-Debugging-Erweiterung, nachdem der Download abgeschlossen ist.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Öffnen Sie dann das Quellcodeverzeichnis, klicken Sie auf Debuggen -> Konfiguration öffnen, die Datei launch.json wird geöffnet.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Gemäß der Abbildung oben können Sie nach der Konfiguration dieser drei Parameter PHP-Code in 1.php im aktuellen Verzeichnis schreiben und Haltepunkte im PHP-Quellcode festlegen direktes Debuggen.

Die Debugging-Umgebung ist eingerichtet.

3. PHP-Deserialisierungs-Quellcode-Analyse

Im Allgemeinen gibt es bei der PHP-Deserialisierung normalerweise zwei Funktionen, Serialisierung und Deserialisierung, die natürlich paarweise auftreten nicht notwendig. Es gibt auch zwei magische Methoden __sleep() und __wakeup(). Wie wir alle wissen, bedeutet Serialisierung lediglich, dass Objekte in Dateien gespeichert werden, während Deserialisierung genau das Gegenteil bedeutet. Die Objekte werden aus der Datei ausgelesen und instanziiert.

Als nächstes verwenden wir basierend auf der oben eingerichteten Debugging-Umgebung dynamisches Debugging, um intuitiv darzustellen, was Serialisierung und Deserialisierung in PHP (Version 7.3.0) erfolgt.

3.1 Quellcodeanalyse serialisieren

Schreiben wir zunächst eine einfache Demo, die die __sleep magische Funktion nicht enthält:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Dann suchen wir global nach der Funktion serialize im Quellcode und finden diese Funktion in der Datei var.c. Wir setzen einen Haltepunkt direkt unter den Funktionsheader und beginnen mit dem Debuggen.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir können sehen, dass wir nach einigen Vorbereitungsarbeiten mit der Serialisierungsverarbeitungsfunktion beginnen und anschließend die Funktion php_var_serialize ausführen.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir werden hier weiterhin der php_var_serialize_intern-Funktion folgen. Da es viele Funktionscodes gibt, haben wir nur die ausgeschnitten Wichtige Teile hier. Die Funktion befindet sich immer noch in der var.c-Datei.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Die Struktur der gesamten Funktion ist ein Schalterfall, und der Typ der Strukturvariante wird durch das Makro Z_TYPE_P analysiert (dieses Makro wird zu struc-> erweitert). ;u1.v.type), um den zu serialisierenden Typ zu bestimmen, und geben Sie dann den entsprechenden CASE-Teil für den Betrieb ein. Die folgende Abbildung zeigt die Typdefinition.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Anhand der Nummer 8 im roten Feld oben wissen wir, dass es in ein Objekt serialisiert werden muss IS_OBJECT und geben Sie den entsprechenden CASE-Zweig ein:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir sehen den Zeitpunkt des Aufrufs der magischen Funktion __sleep im Bild oben. Da diese Funktion in der von uns geschriebenen Demo nicht vorhanden ist, wird der Prozess nicht in diesen Zweig eintreten. Verschiedene Zweige repräsentieren unterschiedliche Verarbeitungsabläufe. Wir werden uns den Prozess mit der magischen Funktion __sleep später ansehen.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Da es im obigen Fall IS_OBJECT-Zweig keinen Prozesstreffer gibt und es in diesem Fall keine Break-Anweisung gibt, wird die Ausführung mit dem IS_ARRAY-Zweig fortgesetzt, wo die Die Klasse wird aus dem Namen der Struc-Struktur extrahiert, ihre Länge berechnet und der Buf-Struktur zugewiesen. Anschließend wird die in der Klasse zu serialisierende Struktur extrahiert und im Hash-Array gespeichert.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Der nächste Schritt besteht darin, die Funktion php_var_serialize_intern zu verwenden, um das gesamte Hash-Array rekursiv zu analysieren, den Variablennamen und -wert daraus zu extrahieren, eine Formatanalyse durchzuführen, und schließen Sie das Parsen ab. Die Zeichenfolge wird in die Buf-Struktur gespleißt. Wenn der gesamte Prozess abgeschlossen ist, wird die gesamte Zeichenfolge schließlich vollständig in der flexiblen Array-Struktur buf gespeichert.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wie aus dem roten Kästchen im Bild oben ersichtlich ist, stimmt es mit dem Endergebnis überein. Als nächstes modifizieren wir die Demo leicht und fügen die magische Funktion __sleep hinzu. Laut offizieller Dokumentation muss die Funktion __sleep ein Array zurückgeben. Wir haben in dieser Funktion auch eine Klassenmitgliedsfunktion aufgerufen. Beobachten Sie sein spezifisches Verhalten.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Der vorherige Vorgang ist genau derselbe und wird hier nicht wiederholt. Beginnen wir am Verzweigungspunkt.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir folgen direkt der php_var_serialize_call_sleep-Funktion.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Hier folgen wir weiter call_user_function Laut Makrodefinition ruft es hier tatsächlich einige Kopieraktionen auf , werden keine Screenshots erstellt und der Prozess fährt mit dem Aufruf der Funktion _call_user_function_ex fort. zend_call_function

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Funktion

, unter tatsächlichen Umständen müssen wir einige unserer eigenen Dinge in zend_call_function tun, wobei PHP die auszuführenden Vorgänge vorantreibt in PHP In Ihrem eigenen __sleep Engine-Stack wird es später einzeln analysiert (dh der entsprechende OPCODE wird analysiert). zend_vm

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Der Prozess hier wird diesen Zweig erreichen, wir folgen der Funktion

. zend_execute_ex

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir können hier sehen, dass in ZEND_VM der gesamte Verarbeitungsablauf eine while(1)-Schleife ist, die die Vorgänge im ZEND_VM-Stack kontinuierlich analysiert. Die ZEND_VM-Engine im roten Feld im obigen Bild verwendet die Methode

, um an die entsprechende Verarbeitungsfunktion zu senden. ZEND_FASTCALL

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Da wir die Mitgliedsfunktion show in

aufgerufen haben, suchen wir hier zuerst show, und dann werden wir die Die folgenden Operationen werden für die nächste Runde des neuen Parsens (hier werden die Operationen in der Show verarbeitet) weiterhin in den ZEND_VM-Stapel verschoben, bis die gesamte Operation analysiert ist. Wir werden hier nicht weiter darauf eingehen. __sleep

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Erinnern Sie sich noch an den obigen ausgehenden Parameter retval, der der Rückgabewert von __sleep ist? Das Bild oben zeigt natürlich das erste Element x des zurückgegebenen Arrays Sie können die Variable auch direkt einchecken.


Nach einem so großen Kreis führen verschiedene Wege zum gleichen Ziel. Nach der Verarbeitung einer Reihe von Operationen in der Funktion _sleep wird die Funktion php_var_serialize_class verwendet, um den Klassennamen zu serialisieren und die Struktur im Rückgabewert ihres _sleep rekursiv zu serialisieren Funktion. Abschließend werden die Ergebnisse in der buf-Struktur gespeichert. An diesem Punkt ist der gesamte Serialisierungsprozess abgeschlossen.

3.1.1 Zusammenfassung des Serialisierungsprozesses

Fassen wir den Serialisierungsprozess zusammen:

Wenn es keine magische Funktion gibt, serialisieren Sie den Klassennamen –> ; Verwenden Sie Rekursion, um die verbleibende Struktur zu serialisieren.

Wenn es eine magische Funktion gibt, rufen Sie die magische Funktion __sleep auf–>Verwenden Sie die ZEND_VM-Engine, um PHP-Operationen zu analysieren –>Ein Array von Strukturen zurückgeben, die serialisiert werden müssen– >Serialisierungsklassenname –> Rekursive Serialisierung der Rückgabewertstruktur von __sleep nutzen.

3.2 Quellcodeanalyse deserialisieren

Nachdem wir den Serialisierungsprozess gelesen haben, schauen wir uns als Nächstes den unserialize-Prozess aus der einfachsten Demo an. Dieses Beispiel enthält keine magischen Funktionen.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Die Methode ist die gleiche wie oben, unserializeDer Quellcode befindet sich auch in der var.c-Datei.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Das obige Bild zeigt die neuen Funktionen in PHP7, gefilterte Deserialisierung, entsprechend allowed_classes Stellen Sie die Situation auf Filter ein die entsprechenden PHP-Objekte, um eine illegale Dateninjektion zu verhindern. Die gefilterten Objekte werden in __PHP_Incomplete_Class对-Objekte umgewandelt und können nicht direkt verwendet werden. Dies hat jedoch keine Auswirkungen auf den Deserialisierungsprozess und wird hier nicht im Detail erläutert. Wir folgen mit der Funktion php_var_unserialize.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir folgen hier weiterhin der php_var_unserialize_internalFunktion.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Der wichtigste interne Vorgang dieser Funktion besteht darin, die Zeichenfolge zu analysieren und dann zum entsprechenden Verarbeitungsprozess zu springen. Der erste Buchstabe 0 wird in der obigen Abbildung analysiert, was die Deserialisierung in ein Objekt darstellt.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Hier wird zunächst der Objektname analysiert und eine Tabellensuche durchgeführt, um zu bestätigen, dass das Objekt tatsächlich existiert.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Nach Abschluss der oben genannten Vorgänge haben wir unser eigenes neues Objekt basierend auf dem Objektnamen new erstellt und initialisiert, aber unser Deserialisierungsvorgang ist immer noch fehlgeschlagen. Fertig, folgen wir mit der object_common2-Funktion hochfahren.

Hier sehen wir die Beurteilung und Erkennung magischer Funktionen, aber der aufrufende Teil ist nicht hier. Folgen wir weiterhin der Funktion „process_nested_data“.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Es scheint, dass diese Funktion eine WHILE-Schleife verwendet, um die verbleibenden Teile einzeln zu analysieren. ·Sie enthält zwei php_var_unserialize_internal-Funktionen. Der erste analysiert den Namen und der zweite analysiert den dem Namen entsprechenden Wert. Nachdem die Funktion „process_nested_data“ ausgeführt wurde, ist die Zeichenfolgenanalyse abgeschlossen, der Hauptinhalt des Deserialisierungsvorgangs ist abgeschlossen und der Prozess steht kurz vor dem Ende.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Schicht für Schicht zur ursprünglichen Funktion zurückkehren PHP_FUNCTION Wir sehen, dass einige Abschlussarbeiten durchgeführt wurden, der angewendete Speicherplatz freigegeben und die Deserialisierung abgeschlossen ist. Unsere magische Funktion __wakeup wird hier nicht aufgerufen. Um den Aufrufzeitpunkt von __wakeup herauszufinden, modifizieren wir die Demo hier.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Eine neue Runde des Debuggens beginnt hier. Es wurde festgestellt, dass nach Abschluss der Serialisierung der Aufruf, den wir erwarten, im Release-Bereich PHP_VAR_UNSERIALIZE_DESTROY angezeigt wird.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Erinnern Sie sich noch an das VAR_WAKEUP_FLAG-Flag, wenn __wakeup während des Deserialisierungsprozesses gefunden wird? Wenn Sie hier das bar_dtor_hash-Array durchlaufen und auf dieses Flag stoßen, wird der Aufruf von __wakeup offiziell gestartet Die eingeführte __sleep-Aufrufmethode ist genau dieselbe und wird hier nicht wiederholt. Zu diesem Zeitpunkt sind alle Deserialisierungsprozesse abgeschlossen.

3.2.1 Zusammenfassung des Serialisierungsprozesses

Aus dem oben Gesagten können wir ersehen, dass der Deserialisierungsprozess im Vergleich zum Serialisierungsprozess nicht vom Vorhandensein magischer Funktionen abhängt. Unterschiede im Prozess zu schaffen. Der Deserialisierungsprozess läuft wie folgt ab:

Holen Sie sich die deserialisierte Zeichenfolge –> Deserialisieren Sie sie entsprechend dem Typ –> Suchen Sie in der Tabelle nach der entsprechenden Deserialisierungsklasse –> –> new erstellt eine neue Instanz –> analysiert iterativ die magische Funktion __wakeup und gibt den Speicherplatz frei –> .

4. PHP-Deserialisierungsschwachstelle

Mit der oben genannten Quellcodegrundlage untersuchen wir nun die Schwachstelle CVE-2016-7124 (Umgehung der magischen Funktion __wakeup).

Daher gelten für die Schwachstelle bestimmte Versionsanforderungen. Wir verwenden eine andere oben kompilierte PHP-Version (5.6.10), um diese Schwachstelle zu reproduzieren und zu debuggen.

Zuerst reproduzieren wir die Schwachstelle:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir können hier sehen, dass die TEST-Klasse nur ein Element $a enthält, und wir desequenzieren es hier beim Ändern Der Wert, der die Anzahl der Elemente in der Elementzeichenfolge darstellt, löst diese Sicherheitslücke aus. Diese Klasse vermeidet den Aufruf der magischen Funktion __wakeup.

Natürlich wurde beim Auslösen der Sicherheitslücke auch ein interessantes Phänomen entdeckt. Dies ist nicht die einzige auslösende Methode.

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Die Deserialisierungsvorgänge, die den vier Nutzlasten im obigen Bild entsprechen, lösen diese Sicherheitslücke aus. Obwohl die folgenden vier Schwachstellen auslösen, gibt es einige geringfügige Unterschiede. Hier ändern wir den Code leicht:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Aus der obigen Abbildung können wir ersehen, dass in der deserialisierten Zeichenfolge, solange die Elemente in der Parsing-Klasse angezeigt werden, diese Sicherheitsanfälligkeit vorliegt wird immer dann ausgelöst, wenn ein Fehler auftritt. Das Ändern der internen Vorgänge des Klassenelements (z. B. Ändern der Zeichenfolgenlänge, des Klassenvariablentyps usw. in der Abbildung oben) führt jedoch dazu, dass die Zuweisung der Klassenmitgliedsvariablen fehlschlägt. Nur wenn die Anzahl der Klassenmitglieder geändert wird (größer als die ursprüngliche Anzahl der Mitglieder), kann der Erfolg der Zuweisung von Klassenmitgliedern garantiert werden.

Schauen wir uns das Problem durch Debuggen an:

Nach unserer Analyse des Deserialisierungsquellcodes im dritten Teil vermuten wir, dass es bei der endgültigen Analyse auftreten könnte Variables Problem. Hier gelangen wir direkt zum Debugger für dynamisches Debuggen:

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wir sehen, dass diese Version im Vergleich zum Quellcode der Version 7.3.0 über keine Filterparameter verfügt und wurde bestanden. Bei so vielen Iterationsversionen scheint der Verarbeitungsprozess für niedrigere Versionen jetzt relativ einfach zu sein. Die allgemeine harmonische Logik hat sich hier jedoch nicht geändert. Die gleiche Logik wird hier nicht wiederholt. Wir werden den Unterschied (object_common2-Funktion) direkt verfolgen, der der Code für die Verarbeitung von Mitgliedsvariablen in der Klasse ist 🎜>

Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

In der Funktion object_common2 gibt es zwei Hauptoperationen: Process_nested_data analysiert iterativ die Daten in der Klasse und den Aufruf der magischen Funktion __wakeup und wenn die Funktion Process_nested_data Wenn die Analyse fehlschlägt, wird direkt der Wert 0 zurückgegeben. Die nachfolgende __wakeup-Funktion kann nicht aufgerufen werden.


Hier ist die Erklärung, warum es mehr als eine Nutzlast gibt, die die Schwachstelle auslöst.


Schwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung

Wenn nur die Anzahl der Klassenmitglieder geändert wird, kann die while-Schleife einmal abgeschlossen werden, wodurch die Mitgliedsvariablen in unserer Klasse vollständig zugewiesen werden können. Beim Ändern der internen Mitgliedsvariablen schlägt der Funktionsaufruf pap_var_unserialize fehl. Anschließend werden die Funktionen zval_dtor und FREE_ZVAL aufgerufen, um den aktuellen Schlüssel-(Variablen-)Speicherplatz freizugeben, was dazu führt, dass die Variablenzuweisung in der Klasse fehlschlägt.


Andererseits gibt es in der PHP7.3.0-Version hier keinen Aufrufprozess, er wird nur einfach markiert und das Timing des gesamten Aufrufprozesses der magischen Funktion wird an den Punkt verschoben, an dem Die Daten werden freigegeben. Dadurch wird dieses Bypass-Problem vermieden. Diese Sicherheitslücke sollte durch einen logischen Fehler verursacht werden.

Das obige ist der detaillierte Inhalt vonSchwachstelle beim Parsen der PHP-Kernelschicht durch Deserialisierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:freebuf.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen