Heim  >  Artikel  >  Backend-Entwicklung  >  PHP-Kurzanalyse der Wissenspunkte der Deserialisierungsstruktur

PHP-Kurzanalyse der Wissenspunkte der Deserialisierungsstruktur

WBOY
WBOYnach vorne
2022-07-29 15:18:582021Durchsuche

Dieser Artikel führt Sie hauptsächlich in das relevante Wissen über PHP ein. Bei der Serialisierung handelt es sich tatsächlich um die Umwandlung von Daten in eine reversible Datenstruktur. Der umgekehrte Vorgang wird natürlich Deserialisierung genannt. PHP verwendet zwei Funktionen, um Daten zu serialisieren und zu deserialisieren: Serialize formatiert das Objekt in eine geordnete Zeichenfolge und unserialize stellt die Zeichenfolge im Originalobjekt wieder her. Ich hoffe, dass dies für alle hilfreich ist.

PHP-Kurzanalyse der Wissenspunkte der Deserialisierungsstruktur

(Empfohlenes Tutorial: PHP-Video-Tutorial)

Einführung

Der Zweck der Serialisierung besteht darin, die Übertragung und Speicherung von Daten zu erleichtern. In PHP werden Serialisierung und Deserialisierung im Allgemeinen zum Zwischenspeichern verwendet, beispielsweise zum Sitzungs-Caching , Kekse usw.

Gemeinsame magische Methoden bei der Deserialisierung

  • __wakeup() //Bei der Ausführung von unserialize() wird diese Funktion zuerst aufgerufen

  • __sleep() //Wenn serialize() ausgeführt wird, wird diese Funktion zuerst aufgerufen ?? context Wird ausgelöst, wenn die Methode

  • __get() //Diese Methode wird aufgerufen, wenn Daten aus unzugänglichen Eigenschaften gelesen werden oder der Schlüssel nicht vorhanden ist

  • __set() //Wird zum Schreiben von Daten in unzugängliche Eigenschaften verwendet. Eigenschaften

  • __isset() //Wird ausgelöst, wenn isset() oder empty() für eine unzugängliche Eigenschaft aufgerufen wird

  • __isset() //Wird ausgelöst, wenn unset() für eine unzugängliche Eigenschaft verwendet wird

  • __toString() / /Ausgelöst, wenn die Klasse als String verwendet wird

  • __invoke() //Ausgelöst, wenn versucht wird, das Objekt als Funktion aufzurufen

  • Deserialisierung umgeht den kleinen Trick

  • php7.1+ Die Serialisierung reagiert nicht auf Klassenattribute
  • Wir haben zuvor gesagt, dass dem Serialisierungsergebnis x00*x00 vorangestellt wird, wenn die Variable geschützt ist.

  • Aber in bestimmten Versionen ab 7.1 gilt für Klassenattribute, die nicht empfindlich sind, beispielsweise das folgende Beispiel gibt weiterhin abc aus, auch wenn kein x00*x00 vorhanden ist
  • PHP7 < 7.0.10

    Verwendung: Wenn der Wert, der die Anzahl der Objektattribute in der serialisierten Zeichenfolge darstellt, größer ist als die tatsächliche Anzahl der Attribute, wird die Ausführung von __wakeup übersprungen
Für Folgendes: So ein Brauch class

<?php
class test{
    protected $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function  __destruct(){
        echo $this->a;
    }
}
unserialize(&#39;O:4:"test":1:{s:1:"a";s:3:"abc";}&#39;);

Wenn Sie unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');Die Ausgabe ausführen Ergebnis ist 666

und der Wert der Anzahl der Objektattribute wird erhöht und ausgeführt unserialize('O:4:"test":2:{s:1:"a"; s:3:"abc";}');Das Ausgabeergebnis ist abc

x00*x00

但在特定版本7.1以上则对于类属性不敏感,比如下面的例子即使没有x00*x00也依然会输出abc

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function __wakeup(){
        $this->a=&#39;666&#39;;
    }
    public function  __destruct(){
        echo $this->a;
    }
}

绕过_wakeup(CVE-2016-7124)

版本:

PHP5 < 5.6.25

PHP7 < 7.0.10

利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

对于下面这样一个自定义类

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = &#39;abc&#39;;
    }
    public function  __destruct(){
        echo $this->a.PHP_EOL;
    }
}
function match($data){
    if (preg_match(&#39;/^O:\d+/&#39;,$data)){
        die(&#39;you lose!&#39;);
    }else{
        return $data;
    }
}
$a = &#39;O:4:"test":1:{s:1:"a";s:3:"abc";}&#39;;
// +号绕过
$b = str_replace(&#39;O:4&#39;,&#39;O:+4&#39;, $a);
unserialize(match($b));
// serialize(array($a));
unserialize(&#39;a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}&#39;);

如果执行unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');输出结果为666

而把对象属性个数的值增大执行unserialize('O:4:"test":2:{s:1:"a";s:3:"abc";}');输出结果为abc

绕过部分正则

preg_match('/^O:d+/')匹配序列化字符串是否是对象字符串开头,这在曾经的CTF中也出过类似的考点

利用加号绕过(注意在url里传参时+要编码为%2B)

serialize(array(a ) ) ; / / a));//a));//a为要反序列化的对象(序列化结果开头是a,不影响作为数组元素的$a的析构)

<?php
class test{
    public $a;
    public $b;
    public function __construct(){
        $this->a = &#39;abc&#39;;
        $this->b= &$this->a;
    }
    public function  __destruct(){

        if($this->a===$this->b){
            echo 666;
        }
    }
}
$a = serialize(new test());

利用引用

rrreee

上面这个例子将$b设置为$a的引用,可以使$a永远与$bUnter Umgehung einiger regulärer Regeln

preg_match('/^O:d+/') Übereinstimmt, ob die serialisierte Zeichenfolge mit einer Objektzeichenfolge beginnt. Dies war ein ähnlicher Testpunkt in früheren CTFs.

Verwenden Sie das Pluszeichen zum Umgehen (beachten Sie, dass + als %2B codiert werden muss, wenn Parameter in der URL übergeben werden).

serialize(array(a ) ) ; / / a));//a));//a ist das zu deserialisierende Objekt (das Serialisierungsergebnis beginnt mit a, was keine Auswirkungen hat (die Verwendung als Array) Zerstörung des Elements $a)

rrreee

Referenz verwenden

rrreee

Das obige Beispiel setzt $b auf eine Referenz von $a, was Folgendes bewirken kann $a ist immer gleich $b

Hexadezimal umgeht die ZeichenfilterungO:4:"test":2:{s:4:"%00*% 00a" ;s:3:"abc";s:7:"%00test%00b";s:3:"def";}

🎜kann geschrieben werden als🎜🎜O:4:"test":2:{ S:4: „

Das obige ist der detaillierte Inhalt vonPHP-Kurzanalyse der Wissenspunkte der Deserialisierungsstruktur. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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