首頁 > 後端開發 > PHP問題 > php淺析反序列化結構知識點

php淺析反序列化結構知識點

WBOY
發布: 2023-03-16 16:38:01
轉載
2044 人瀏覽過

本篇文章主要為大家介紹了關於PHP的相關知識,序列化其實就是將資料轉化成一種可逆的資料結構,自然,逆向的過程就叫做反序列化。 php將資料序列化和反序列化會用到兩個函數:serialize 將物件格式化成有序的字串、unserialize 將字串還原成原來的對象,希望對大家有幫助。

php淺析反序列化結構知識點

(推薦教學:PHP影片教學

簡介

序列化的目的是方便資料的傳輸和存儲,在PHP中,序列化和反序列化一般用做緩存,例如session緩存,cookie等。

反序列化中常見的魔術方法

  • __wakeup() //執行unserialize()時,先會呼叫這個函數

  • __sleep() //執行serialize()時,先會呼叫這個函數

  • #__destruct() //物件被銷毀時觸發

  • __call() //在物件上下文中呼叫不可存取的方法時觸發

  • #__callStatic() //在靜態上下文中呼叫不可存取的方法時觸發

  • __get() //用於從不可存取的屬性讀取資料或不存在這個鍵都會呼叫此方法

  • __set() / /用於將資料寫入不可存取的屬性

  • __isset() //在不可存取的屬性上呼叫isset()或empty()觸發

  • __unset() //在不可存取的屬性上使用unset()時觸發

  • #__toString() //把類別當作字串使用時觸發

  • __invoke() //當嘗試將物件呼叫為函數時觸發

反序列化繞過小Trick

php7 .1 反序列化對類別屬性不敏感

我們前面說瞭如果變數前是protected,序列化結果會在變數名稱前加上\x00*\x00

#但在特定版本7.1以上則對於類別屬性不敏感,例如下面的範例即使沒有\x00*\x00也依然會輸出abc

<?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;);
登入後複製

繞過_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 __wakeup(){
        $this->a=&#39;666&#39;;
    }
    public function  __destruct(){
        echo $this->a;
    }
}
登入後複製

如果執行

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裡傳參時要編碼為+)

serialize(array(a ) ) ; / / a));//a));//a為要反序列化的物件(序列化結果開頭是a,不影響作為陣列元素的$a的析構)

<?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;);
登入後複製

利用引用

<?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());
登入後複製
上面這個例子將

$b設定為$a的引用,可以使$a永遠與$b相等

16進位繞過字元的過濾

O:4:「test」:2:{ s:4:“

以上是php淺析反序列化結構知識點的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
php
來源:jb51.net
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板