php序列化漏洞理解
阿新 • • 發佈:2018-04-27
觸發 lean 自動 就是 bool http alt his const
如果服務器能夠接收我們反序列化過的字符串、並且未經過濾的把其中的變量直接放進這些魔術方法裏面的話,就容易造成很嚴重的漏洞了。
0x05序列化格式
0x01什麽是序列化
序列化就是將我們的 對象轉變成一個字符串,保存對象的值方便之後的傳遞與使用。 0x02為什麽要序列化 如果為一個腳本中想要調用之前一個腳本的變量,但是前一個腳本已經執行完畢,所有的變量和內容釋放掉了,我們要如何操作呢?難道要前一個腳本不斷的循環,等待後面腳本調用?這肯定是不現實的。serialize和unserialize就是用來解決這一問題的。serialize可以將變量轉換為字符串並且在轉換中可以保存當前變量的值;unserialize則可以將serialize生成的字符串變換回變量。 0x03怎樣產生了漏洞 這些就是我們要關註的幾個魔術方法了,如果服務器能夠接收我們反序列化過的字符串、並且未經過濾的把其中的變量直接放進這些魔術方法裏面的話,就容易造成很嚴重的漏洞了。當傳給 nserialize() 的參數可控時,我們可以通過傳入一個精心構造的序列化字符串,從而控制對象內部的變量甚至是函數。- 構造函數__construct():當對象創建(new)時會自動調用。但在unserialize()時是不會自動調用的。
- 析構函數__destruct():當對象被銷毀時會自動調用。
- __wakeup() :如前所提,unserialize()時會自動調用。
- __toString()當一個對象被當作一個字符串使用
- __sleep() 在對象在被序列化之前運行
0x04如何利用序列化漏洞
unserialize()後會導致__wakeup() 或__destruct()的直接調用,中間無需其他過程。因此最理想的情況就是一些漏洞/危害代碼在__wakeup() 或__destruct()中,從而當我們控制序列化字符串時可以去直接觸發它們。- String : s:size:value;
- Integer : i:value;
- Boolean : b:value;(保存1或0)
- Null : N;
- Array : a:size:{key definition;value definition;(repeated per element)}
-
Object : O:strlen(object name):object name:object size:{s:strlen(property name):property name:property definition;(repeated per property)
0x06實例
這裏借用別人的一個很好的例子來說明一下這個問題。我們針對__wakeup()場景做實驗。
建立一個index2的php文件,如下:
1 <?php 2 class chybeta{ 3 var $test = ‘123‘; 4 function __wakeup(){ 5 $fp = fopen("shell.php","w") ; 6 fwrite($fp,$this->test); 7 fclose($fp); 8 } 9 } 10 $class3 = $_GET[‘test‘]; 11 print_r($class3); 12 echo "</br>"; 13 $class3_unser = unserialize($class3); 14 require "shell.php"; 15 // 為顯示效果,把這個shell.php包含進來 16 ?>
在同目錄下建立一個空的shell.php文件
我們可以看見上面的存在明顯的漏洞,主要是沒有對接受的test參數做處理,unserialize()後直接調用了魔法方法__wakeup(),該方法就將test直接寫入到了shell.php中。因此我們直接給test傳入一個我們精心構造的參數即可利用漏洞了,例如我們可以構造 test=O:7:"chybeta":1:{s:4:"test";s:19:"";} ,即可看到命令被成功執行。
這是我個人的第一次寫博客,只是希望自己能通過寫加深自己對知識的理解,同時通過寫博客來增加對自己的要求,博客有很多不足,希望大家多多指正,我會一直努力學習。
php序列化漏洞理解