Einführung
Die offizielle Dokumentation führt die PHP-Serialisierung und -Deserialisierung wie folgt ein:
Alle Werte in PHP sind Sie kann die Funktion serialize() verwenden, um eine Zeichenfolge zurückzugeben, die einen Bytestream enthält. Die Funktion unserialize() kann den String wieder auf den ursprünglichen Wert von PHP zurücksetzen. Durch die Serialisierung eines Objekts werden alle Variablen des Objekts gespeichert, jedoch nicht die Methoden des Objekts, sondern nur der Klassenname. Um ein Objekt unserialisieren() zu können, muss die Klasse des Objekts definiert worden sein. Wenn Sie ein Objekt der Klasse A serialisieren, wird eine auf Klasse A bezogene Zeichenfolge zurückgegeben, die die Werte aller Variablen im Objekt enthält.
Einfach ausgedrückt ist Serialisierung der Prozess der Konvertierung von Objekten in Strings, und Deserialisierung ist der Prozess der Wiederherstellung von Objekten aus Strings.
Umgebung
Der im Artikel beschriebene Inhalt wird in der folgenden Umgebung verwendet:
PHP7.3.1, SDKVSCodeC++ und C
Der online offengelegte Prozess zur Ausführung der Parameter-Deserialisierung ist sehr detailliert, weist jedoch in einigen Details einige Mängel auf, einschließlich des Syntaxunterschieds zwischen Serialisierung und Deserialisierung.
Unterschiedsprobleme
1. Serialisierung
Wir analysieren, indem wir den PHP-Kernel-Quellcode kompilieren Es wurde festgestellt, dass die PHP-Serialisierung standardmäßig Folgendes zur Objektkonvertierung hinzufügt, um sie zu einer Zeichenfolge zu verketten.
[var.c] Line:882 static void php_var_serialize_intern() Line:896 if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) { smart_str_appendl(buf, "C:", 2); smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name)); smart_str_appendl(buf, ":\"", 2); smart_str_append(buf, Z_OBJCE_P(struc)->name); smart_str_appendl(buf, "\":", 2); smart_str_append_unsigned(buf, serialized_length); smart_str_appendl(buf, ":{", 2); smart_str_appendl(buf, (char *) serialized_data, serialized_length); smart_str_appendc(buf, '}'); } Line:952 smart_str_appendl(buf, ":{", 2); Line:995 smart_str_appendc(buf, '}');
Schauen wir uns den obigen Code an. PHP verwendet smart_str_appendl, um die serialisierte Zeichenfolge vor und nach: {and} zu verbinden und die Serialisierungslogik ab Zeile 882 von var.c einzugeben. Das Serialisierungs-String-Spleißen wird in Zeile 896 durchgeführt, und die Zeilen 952 und 995 werden für Inline-Methoden gespleißt.
2. Deserialisierung
Bei der Deserialisierung wird die serialisierte Zeichenfolge gemäß bestimmten grammatikalischen Regeln konvertiert und wiederhergestellt.
[var_unserialize.c] Line:655 static int php_var_unserialize_internal() Line:674{ YYCTYPE yych; static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7); yych = *YYCURSOR; switch (yych) { case 'C': case 'O': goto yy4; case 'N': goto yy5; case 'R': goto yy6; case 'S': goto yy7; case 'a': goto yy8; case 'b': goto yy9; case 'd': goto yy10; case 'i': goto yy11; case 'o': goto yy12; case 'r': goto yy13; case 's': goto yy14; case '}': goto yy15; default: goto yy2; } Line:776 yy15: ++YYCURSOR; { /* this is the case where we have less data than planned */ php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ }
Durch den Kernel-Code können Sie sehen, dass die Deserialisierung in Zeile 655 lexikalisches Scannen verwendet, um die entsprechenden Objekte jeder Symbolkonvertierung zu ermitteln. Es ist ersichtlich, dass } während der Deserialisierung verarbeitet wird. Während der Verarbeitung wird der Zähler nur um eins erhöht und es werden keine anderen Vorgänge ausgeführt.
Tatsächliche Auswirkung
Der Unterschied in der Deserialisierungssyntax hat einen großen Einfluss auf die Beurteilung der Deserialisierung durch die Sicherheitsschutzausrüstung. In Snort gibt es eine Regel wie folgt:
alert tcp any any -> any [80,8080,443] (uricontent:".php"; pcre:"/\{\w:.+?\}/"; sid:1; msg:php_serialize;)
Die meisten Zeichen können anstelle von {} in der Angriffsnutzlast verwendet werden, wodurch die Regel ungültig wird.
Zusammenfassung
Unterschiede in der PHP-Serialisierungs- und Deserialisierungssyntax können bei Red-Team-Angriffen ausgenutzt werden, um den Schutz zu umgehen.
Bei der Blue-Team-Verteidigung wird empfohlen, die in der Definition beschriebene Methode zu berücksichtigen, die nicht das Objekt, sondern nur den Namen der Klasse speichert. , fangen den Namen der gespeicherten Klasse und dieselben Zeichen in der Syntax ab, z. B. einen Doppelpunkt zur Verteidigung.
Teilen verwandter Artikel und Tutorials: Tutorial zur Website-Sicherheit
Das obige ist der detaillierte Inhalt vonSyntaxunterschiede zwischen PHP-Serialisierung und -Deserialisierung nutzen, um den Schutz zu umgehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!