詳解PHP反序列化漏洞示例與原理
預備知識
PHP序列化與反序列化
序列化:將一個復雜的數(shù)據(jù)類型(如對象、數(shù)組、變量等)轉(zhuǎn)換為字符串表示,以便于在網(wǎng)絡中傳輸和在數(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加速緩存器opcache,apc,xcache,eAccelerator原理與配置方法實例分析
這篇文章主要介紹了php加速緩存器opcache,apc,xcache,eAccelerator原理與配置方法,結(jié)合實例形式分析了php加速緩存器opcache,apc,xcache,eAccelerator的基本功能、原理及擴展配置相關(guān)操作技巧,需要的朋友可以參考下2020-03-03分享下php5類中三種數(shù)據(jù)類型的區(qū)別
這篇文章主要介紹了php5類中三種數(shù)據(jù)類型的區(qū)別,需要的朋友可以參考下2015-01-01