詳解PHP反序列化漏洞示例與原理
預備知識
PHP序列化與反序列化
序列化:將一個復雜的數(shù)據(jù)類型(如對象、數(shù)組、變量等)轉(zhuǎn)換為字符串表示,以便于在網(wǎng)絡(luò)中傳輸和在數(shù)據(jù)庫中存儲。在PHP語言中使用serialize()函數(shù)實現(xiàn)。
反序列化:將一個序列化的字符串重新轉(zhuǎn)換為一個具體的數(shù)據(jù)類型。在PHP語言中使用unserialize()函數(shù)實現(xiàn)。 PHP對象中只有數(shù)據(jù)會被序列化,方法不會被序列化。
序列化字符串格式
PHP中經(jīng)過序列化的字符串格式如下:
類型:類名長度:“類名”:類屬性數(shù)量:{屬性類型:屬性長度:“屬性內(nèi)容”}
序列化字符串中的屬性命名規(guī)則:如果變量為public,則值保持不變;如果變量為private,則在值開頭加上類名前綴;如果變量為protected,則在值開頭加*符號。
下面給出序列化字符串中的屬性類型:
| 類型 | 解釋 |
|---|---|
| s:length:“value” | 字符串 |
| i:value | 整數(shù)值 |
| d:value | 浮點數(shù)值 |
| b:value | 布爾值 |
| a:length:{…} | 數(shù)組 |
| O:length:“name”:number:{…} | 對象 |
| N | NULL |
PHP魔術(shù)方法
簡介:魔術(shù)方法是一種以2個下劃線開頭的特殊方法,對一個對象執(zhí)行魔術(shù)方法時會覆蓋PHP默認的操作。
常見的PHP魔術(shù)方法如下:
| 方法 | 調(diào)用時間 |
|---|---|
| __construct(構(gòu)造函數(shù)) | 創(chuàng)建新對象時 |
| __destruct (析構(gòu)函數(shù)) | 銷毀對象時 |
| __call | 在對象中調(diào)用不可用方法時 |
| __callStatic | 在上下文中調(diào)用不可用方法時 |
| __get | 讀不可用值時 |
| __set | 寫不可用值時 |
| __isset | 對不可用值調(diào)用isset()或empty()時 |
| __unset | 對不可用值調(diào)用unset()時 |
| __sleep | 序列化對象時 |
| __wakeup | 反序列化對象時 |
| __toString | 對象被作為字符串使用時 |
| __invoke | 嘗試以調(diào)用函數(shù)方式調(diào)用對象時 |
示例
<?php
class Test{
public $a="aaa";
private $b="bbb";
protected $c=123;
function __construct($a,$b,$c)
{
$this->a=$a;
$this->b=$b;
$this->c=$c;
echo("Constructor called.<br>");
}
function __destruct()
{
echo("Destructor called.<br>");
}
function show()
{
echo($this->a."\n".$this->b."\n".$this->c."<br>");
}
}
$data=new Test("a",1,1.1);
$data_str=serialize($data);
echo($data_str."\n");
$data_new=unserialize($data_str);
echo("<br>");
$data_new->show();
?>
反序列化漏洞
反序列化漏洞指網(wǎng)站未對被用戶所控制的序列化字符串做檢查,攻擊者提交了精心構(gòu)造的有害序列化字符串,導致惡意代碼被執(zhí)行。常見于PHP、Python、Java等允許對象序列化功能的編程語言中。
在PHP中,導致反序列化漏洞的原因大多是魔術(shù)方法的不規(guī)范使用。(如輸出變量內(nèi)容、寫文件操作、寫數(shù)據(jù)庫操作等參數(shù)用戶可控)
構(gòu)造函數(shù)&析構(gòu)函數(shù)
假設(shè)網(wǎng)站頁面部分代碼編寫如下:
<?php
class Test
{
var $a="aaa";
function __construct($a)
{
$this->a=$a;
echo("Info:<br>".$a);
}
}
$data_new=unserialize($_GET['data']);
var_dump($data_new);
?>
當對象創(chuàng)建(或銷毀)時,程序會輸出對象中三個成員變量的值;程序還從API接口讀取了一個序列化字符串并試圖將其反序列化。此時如果將序列化字符串中的值修改為惡意代碼,類名修改為Test,會導致反序列化漏洞攻擊。
EXP:O:4:“Test”:1:{s:4:“test”;s:29:“<script>alert(‘xss’)</script>”;}

CVE-2016-7124
在PHP5 <5.6.25、PHP7 <7.0.10的環(huán)境中,如果類中存在__wakeup魔術(shù)方法,則在反序列化之前會先調(diào)用該方法。但當序列化字符串中屬性數(shù)量大于真實屬性數(shù)量時,該方法不會執(zhí)行。
<?php
class Test
{
var $mess="111";
function __wakeup()
{
$this->mess="failed";
echo("Please try again.<br>");
}
}
$new_data=unserialize($_GET['ins']);
var_dump($new_data);
?>代碼中,當反序列化一個字符串時,程序會執(zhí)行__wakeup方法,將$mess設(shè)置為字符串,并顯示失敗信息。此時把序列化字符串中的屬性數(shù)量值改大,__wakeup方法會失效。
EXP:http://127.0.0.1/serialize.php?ins=O:4:“Test”:2:{s:4:“mess”;s:25:"
<script>alert(1)</script>";}
到此這篇關(guān)于詳解PHP反序列化漏洞示例與原理的文章就介紹到這了,更多相關(guān)PHP反序列化漏洞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用PHP將Unicode 轉(zhuǎn)化為UTF-8的實現(xiàn)方法(推薦)
下面小編就為大家?guī)硪黄肞HP將Unicode 轉(zhuǎn)化為UTF-8的實現(xiàn)方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
Thinkphp結(jié)合ajaxFileUpload實現(xiàn)異步圖片傳輸示例
這篇文章主要給大家介紹了利用Thinkphp結(jié)合ajaxFileUpload實現(xiàn)異步圖片傳輸?shù)姆椒ǎ闹薪o出了詳細的示例代碼,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03
PHP數(shù)組 為文章加關(guān)鍵字連接 文章內(nèi)容自動加鏈接
PHP給文章加關(guān)鍵字連接,像163文章內(nèi)容自動加鏈接效果,其實很多php網(wǎng)站管理系統(tǒng)里面都有,可以參考里面的代碼。2011-12-12
PHP模擬asp.net的StringBuilder類實現(xiàn)方法
這篇文章主要介紹了PHP模擬asp.net的StringBuilder類實現(xiàn)方法,較為簡單的模擬了StringBuilder類針對文本的基本操作技巧,需要的朋友可以參考下2015-08-08

