您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“PHP反序列化的概念和用法”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
序列化:主要是將變量進(jìn)行轉(zhuǎn)換,使其變?yōu)樽址?,序列化一個(gè)對(duì)象將會(huì)保存對(duì)象的所有變量,但是不會(huì)保存對(duì)象的方法,只會(huì)保存類的名字。在程序執(zhí)行結(jié)束時(shí),內(nèi)存數(shù)據(jù)便會(huì)立即銷毀,變量所儲(chǔ)存的數(shù)據(jù)便是內(nèi)存數(shù)據(jù),而文件、數(shù)據(jù)庫(kù)是“持久數(shù)據(jù)”,因此PHP序列化就是將內(nèi)存的變量數(shù)據(jù)“保存”到文件中的持久數(shù)據(jù)的過(guò)程。方便保存和傳輸,并且可以達(dá)到節(jié)省空間的目的
反序列化:主要是在特定的時(shí)候?qū)⑿蛄谢D(zhuǎn)換為字符串的內(nèi)容再轉(zhuǎn)換為原來(lái)的變量繼續(xù)使用,簡(jiǎn)單來(lái)理解起來(lái)就是將序列化過(guò)存儲(chǔ)到文件中的數(shù)據(jù),恢復(fù)到程序代碼的變量表示形式的過(guò)程,恢復(fù)到變量序列化之前的結(jié)果。
PHP反序列化的相關(guān)函數(shù)主要是:serialize()和unserialize()
其中serialize()可以將變量轉(zhuǎn)換為字符串,并且在轉(zhuǎn)換的過(guò)程中保存當(dāng)我變量的值
而unserialize()2可以將serialize()轉(zhuǎn)換的字符串再轉(zhuǎn)換為變量
主要包括:類,變量,方法,對(duì)象(如下圖)
__construct 當(dāng)一個(gè)對(duì)象創(chuàng)建時(shí)被調(diào)用,
__destruct 當(dāng)一個(gè)對(duì)象銷毀時(shí)被調(diào)用,
__toString 當(dāng)一個(gè)對(duì)象被當(dāng)作一個(gè)字符串被調(diào)用。
__wakeup() 使用unserialize時(shí)觸發(fā)
__sleep() 使用serialize時(shí)觸發(fā)
__destruct() 對(duì)象被銷毀時(shí)觸發(fā)
__call() 在對(duì)象上下文中調(diào)用不可訪問(wèn)的方法時(shí)觸發(fā)
__callStatic() 在靜態(tài)上下文中調(diào)用不可訪問(wèn)的方法時(shí)觸發(fā)
__get() 用于從不可訪問(wèn)的屬性讀取數(shù)據(jù)
__set() 用于將數(shù)據(jù)寫入不可訪問(wèn)的屬性
__isset() 在不可訪問(wèn)的屬性上調(diào)用isset()或empty()觸發(fā)
__unset() 在不可訪問(wèn)的屬性上使用unset()時(shí)觸發(fā)
__toString() 把類當(dāng)作字符串使用時(shí)觸發(fā),返回值需要為字符串
__invoke() 當(dāng)腳本嘗試將對(duì)象調(diào)用為函數(shù)時(shí)觸發(fā)
<?php class User { public $age = 0; public $name = ''; public function PrintData() { echo 'User '.$this->name.'is'.$this->age.'years old. <br />'; } } //創(chuàng)建一個(gè)對(duì)象 $user = new User(); // 設(shè)置數(shù)據(jù) $user->age = 20; $user->name = 'daye'; //輸出數(shù)據(jù) $user->PrintData(); //輸出序列化之后的數(shù)據(jù) echo serialize($user); ?>
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}
對(duì)象類型:長(zhǎng)度:"類名":類中變量的個(gè)數(shù):{類型:長(zhǎng)度:"值";類型:長(zhǎng)度:"值";......}
反序列化
<?php class User { public $age = 0; public $name = ''; public function PrintData() { echo 'User '.$this->name.' is '.$this->age.' years old. <br />'; } } //重建對(duì)象 $user = unserialize('O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}'); $user->PrintData(); ?>
<?php class test{ public $varr1="abc"; public $varr2="123"; public function echoP(){ echo $this->varr1."<br>"; } public function __construct(){ echo "__construct<br>"; } public function __destruct(){ echo "__destruct<br>"; } public function __toString(){ return "__toString<br>"; } public function __sleep(){ echo "__sleep<br>"; return array('varr1','varr2'); } public function __wakeup(){ echo "__wakeup<br>"; } } $obj = new test(); //實(shí)例化對(duì)象,調(diào)用__construct()方法,輸出__construct $obj->echoP(); //調(diào)用echoP()方法,輸出"abc" echo $obj; //obj對(duì)象被當(dāng)做字符串輸出,調(diào)用__toString()方法,輸出__toString $s =serialize($obj); //obj對(duì)象被序列化,調(diào)用__sleep()方法,輸出__sleep echo unserialize($s); //$s首先會(huì)被反序列化,會(huì)調(diào)用__wake()方法,被反序列化出來(lái)的對(duì)象又被當(dāng)做字符串,就會(huì)調(diào)用_toString()方法。 // 腳本結(jié)束又會(huì)調(diào)用__destruct()方法,輸出__destruct ?>
當(dāng)出現(xiàn)PHP反序列化漏洞的時(shí)候,首先我們可以將想要輸入的變量使用serialize()進(jìn)行序列化,如:O:1:"S":1:{s:4:"test";s:28:"<img src=x onerror=alert(1)>";}
其次,將序列化之后的字符串放到url中。在PHP代碼中使用了unserialize(),則會(huì)自動(dòng)執(zhí)行特定的魔法函數(shù),如果魔法函數(shù)中有其他的一些危險(xiǎn)函數(shù)且是我們可控的,即可進(jìn)行其他操作。
“PHP反序列化的概念和用法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。