日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > php >内容正文

php

php反序列化漏洞原理,PHP反序列化原理及漏洞解析

發(fā)布時(shí)間:2025/3/20 php 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php反序列化漏洞原理,PHP反序列化原理及漏洞解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是PHP序列化

PHP序列化與反序列化的過(guò)程

一個(gè)反序列化漏洞的例子

CVE-2016-7124

一. 什么是PHP序列化與反序列化

1. PHP序列化

PHP序列化是指把變量轉(zhuǎn)化成可保存或傳輸?shù)淖址倪^(guò)程,PHP序列化函數(shù)有serialize、json_encode。

以下例子可以實(shí)現(xiàn)PHP序列化

1

2

3

4

5

6

7

8

9

10

11

12

13<?php

class test

{

public $name = 'jacky';

public $age = '18';

public $heavy = '81.5';

public $boolean = true;

public $null = NULL;

public $array = array(1,2,3,4,5);

}

$jacky = new test;

echo serialize($jacky);

?>

輸出的結(jié)果為

O:4:”test”:6:{s:4:”name”;s:5:”jacky”;s:3:”age”;s:2:”18”;s:5:”heavy”;s:4:”81.5”;s:7:”boolean”;b:1;s:4:”null”;N;s:5:”array”;a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}}

其中每項(xiàng)的標(biāo)識(shí)所代表的含義

標(biāo)識(shí)

含義

s

字符串(string)

i

整型(integer)

b

布爾(boolean)

d

雙精度(double)

N

空(NULL)

a

數(shù)組(array)

同時(shí),序列化過(guò)程中還會(huì)對(duì)不同屬性的變量進(jìn)行不同方式的變化

public的屬性在序列化時(shí),直接顯示屬性名

protected的屬性在序列化時(shí),會(huì)在屬性名前增加0x00*0x00,其長(zhǎng)度會(huì)增加3

private的屬性在序列化時(shí),會(huì)在屬性名前增加0x00classname0x00,其長(zhǎng)度會(huì)增加類(lèi)名長(zhǎng)度+2

2. 反序列化

PHP反序列是指將經(jīng)過(guò)序列化的數(shù)據(jù)轉(zhuǎn)化成原先的狀態(tài),PHP反序列化函數(shù)有unserialize、json_decode。

二. PHP序列化與反序列化的過(guò)程

1. PHP魔法函數(shù)

PHP中包含很多魔法函數(shù),他們可以在某些情況下自動(dòng)執(zhí)行而不需要手動(dòng)調(diào)用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16__construct() #類(lèi)的構(gòu)造函數(shù)

__destruct() #類(lèi)的析構(gòu)函數(shù)

__call() #在對(duì)象中調(diào)用一個(gè)不可訪問(wèn)方法時(shí)調(diào)用

__callStatic() #用靜態(tài)方式中調(diào)用一個(gè)不可訪問(wèn)方法時(shí)調(diào)用

__get() #獲得一個(gè)類(lèi)的成員變量時(shí)調(diào)用

__set() #設(shè)置一個(gè)類(lèi)的成員變量時(shí)調(diào)用

__isset() #當(dāng)對(duì)不可訪問(wèn)屬性調(diào)用isset()或empty()時(shí)調(diào)用

__unset() #當(dāng)對(duì)不可訪問(wèn)屬性調(diào)用unset()時(shí)被調(diào)用。

__sleep() #執(zhí)行serialize()時(shí),先會(huì)調(diào)用這個(gè)函數(shù)

__wakeup() #執(zhí)行unserialize()時(shí),先會(huì)調(diào)用這個(gè)函數(shù)

__toString() #類(lèi)被當(dāng)成字符串時(shí)的回應(yīng)方法

__invoke() #調(diào)用函數(shù)的方式調(diào)用一個(gè)對(duì)象時(shí)的回應(yīng)方法

__set_state() #調(diào)用var_export()導(dǎo)出類(lèi)時(shí),此靜態(tài)方法會(huì)被調(diào)用。

__clone() #當(dāng)對(duì)象復(fù)制完成時(shí)調(diào)用

__autoload() #嘗試加載未定義的類(lèi)

__debugInfo() #打印所需調(diào)試信息

2. 如何進(jìn)行序列化

在對(duì)象被序列化之前,會(huì)檢查是否有__sleep()函數(shù),如果存在,該函數(shù)會(huì)清理對(duì)象,并返回一個(gè)數(shù)組,數(shù)組中包含被序列化的對(duì)象的所有屬性的名稱(chēng)。如果該方法不返回任何內(nèi)容,則序列化后的字符串將變?yōu)镹并提示Notice。__sleep()的預(yù)期用途是提交需要掛起的數(shù)據(jù)或執(zhí)行類(lèi)似的清理任務(wù)。如果有一個(gè)非常大的對(duì)象,不需要完全保存其所有屬性,該功能將非常有用。

在反序列化之前,會(huì)檢查是否具有__wakeup()魔術(shù)方法。如果存在該方法,則在反序列化時(shí)執(zhí)行該方法。__wakeup()魔術(shù)方法可以重構(gòu)對(duì)象可能具有的任何資源。__wakeup()預(yù)期用途是重新建立在序列化期間可能已丟失的任何數(shù)據(jù)庫(kù)連接,并執(zhí)行其他重新初始化任務(wù)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39<?php

class test

{

public $value;

function __construct(){

echo "__construct";

echo "
";

}

function __destruct(){

echo "__destruct";

echo "
";

}

function __wakeup(){

echo "__wakeup";

echo "
";

}

function __toString(){

echo "__toString";

echo "
";

return $this->value;

}

function setValue($parm){

echo "setValue";

echo "
";

$this->value = $parm;

}

}

$test = new test;

$test->setValue("Jacky");

$ser_test = serialize($test);

echo $ser_test."
";

$obj = unserialize($ser_test);

echo $obj."
";

?>

1

2

3

4

5

6

7

8

9

10//output

__construct

setValue

O:4:"test":1:{s:5:"value";s:5:"Jacky";}

__wakeup

__toString

Jacky

__destruct

__destruct

3. __autoloading()函數(shù)

傳統(tǒng)的PHP只能反序列化定義過(guò)的類(lèi),意味著每個(gè)PHP文件都需要包含很多文件,在當(dāng)前主流的PHP框架中,都采用了__autoloading()自動(dòng)加載類(lèi)來(lái)完成這項(xiàng)繁重的工作。在簡(jiǎn)化了工作的同時(shí),也為序列化漏洞造成了便捷。

4. 反序列化過(guò)程中魔術(shù)方法的執(zhí)行順序

__wakeup()> __toString()> __destruct()

三. 一個(gè)反序列化漏洞的例子

右擊查看源代碼,可以看到如下提示

1

2

3

4

5

6

7

8

9

10$user = $_GET["txt"];

$file = $_GET["file"];

$pass = $_GET["password"];

if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){

echo "hello admin!
";

include($file); //hint.php

}else{

echo "you are not admin ! ";

}

首先我們嘗試將$user的值改為welcome to the bugkuctf,由于使用的是file_get_contents()函數(shù),所以需要使用PHP偽協(xié)議來(lái)傳入$user的值,payload如下

下一步處理$file的值,可以看到代碼中有文件包含,并提示了所包含的文件時(shí)hint.php,這里需要使用另一個(gè)PHP偽協(xié)議來(lái)傳入$file的值,payload如下

將出現(xiàn)的字符通過(guò)base64解密,可以得到如下代碼

1

2

3

4

5

6

7

8

9

10

11

12

13<?php

class Flag{//flag.php

public $file;

public function __tostring(){

if(isset($this->file)){

echo file_get_contents($this->file);

echo "
";

return ("good");

}

}

}

?>

可以看到,在flag.php文件中有一個(gè)Flag類(lèi),此外,我們可以用同樣的方法得到index.php文件中的內(nèi)容

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31$txt = $_GET["txt"];

$file = $_GET["file"];

$password = $_GET["password"];

if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){

echo "hello friend!
";

if(preg_match("/flag/",$file)){

echo "不能現(xiàn)在就給你flag哦";

exit();

}else{

include($file);

$password = unserialize($password);

echo $password;

}

}else{

echo "you are not the number of bugku ! ";

}

?>

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的php反序列化漏洞原理,PHP反序列化原理及漏洞解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。