代码编织梦想

什么是PHP序列化

PHP序列化与反序列化的过程

一个反序列化漏洞的例子

CVE-2016-7124

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

1. PHP序列化

PHP序列化是指把变量转化成可保存或传输的字符串的过程,PHP序列化函数有serialize、json_encode。

以下例子可以实现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);

?>

输出的结果为

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;}}

%5Cimage%5CphpUnserialize%5C1.png

其中每项的标识所代表的含义

标识

含义

s

字符串(string)

i

整型(integer)

b

布尔(boolean)

d

双精度(double)

N

空(NULL)

a

数组(array)

同时,序列化过程中还会对不同属性的变量进行不同方式的变化

public的属性在序列化时,直接显示属性名

protected的属性在序列化时,会在属性名前增加0x00*0x00,其长度会增加3

private的属性在序列化时,会在属性名前增加0x00classname0x00,其长度会增加类名长度+2

2. 反序列化

PHP反序列是指将经过序列化的数据转化成原先的状态,PHP反序列化函数有unserialize、json_decode。

二. PHP序列化与反序列化的过程

1. PHP魔法函数

PHP中包含很多魔法函数,他们可以在某些情况下自动执行而不需要手动调用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16__construct() #类的构造函数

__destruct() #类的析构函数

__call() #在对象中调用一个不可访问方法时调用

__callStatic() #用静态方式中调用一个不可访问方法时调用

__get() #获得一个类的成员变量时调用

__set() #设置一个类的成员变量时调用

__isset() #当对不可访问属性调用isset()或empty()时调用

__unset() #当对不可访问属性调用unset()时被调用。

__sleep() #执行serialize()时,先会调用这个函数

__wakeup() #执行unserialize()时,先会调用这个函数

__toString() #类被当成字符串时的回应方法

__invoke() #调用函数的方式调用一个对象时的回应方法

__set_state() #调用var_export()导出类时,此静态方法会被调用。

__clone() #当对象复制完成时调用

__autoload() #尝试加载未定义的类

__debugInfo() #打印所需调试信息

2. 如何进行序列化

在对象被序列化之前,会检查是否有__sleep()函数,如果存在,该函数会清理对象,并返回一个数组,数组中包含被序列化的对象的所有属性的名称。如果该方法不返回任何内容,则序列化后的字符串将变为N并提示Notice。__sleep()的预期用途是提交需要挂起的数据或执行类似的清理任务。如果有一个非常大的对象,不需要完全保存其所有属性,该功能将非常有用。

在反序列化之前,会检查是否具有__wakeup()魔术方法。如果存在该方法,则在反序列化时执行该方法。__wakeup()魔术方法可以重构对象可能具有的任何资源。__wakeup()预期用途是重新建立在序列化期间可能已丢失的任何数据库连接,并执行其他重新初始化任务。

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()函数

传统的PHP只能反序列化定义过的类,意味着每个PHP文件都需要包含很多文件,在当前主流的PHP框架中,都采用了__autoloading()自动加载类来完成这项繁重的工作。在简化了工作的同时,也为序列化漏洞造成了便捷。

4. 反序列化过程中魔术方法的执行顺序

__wakeup()> __toString()> __destruct()

三. 一个反序列化漏洞的例子

%5Cimage%5CphpUnserialize%5C2.png

右击查看源代码,可以看到如下提示

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()函数,所以需要使用PHP伪协议来传入$user的值,payload如下

%5Cimage%5CphpUnserialize%5C3.png

下一步处理$file的值,可以看到代码中有文件包含,并提示了所包含的文件时hint.php,这里需要使用另一个PHP伪协议来传入$file的值,payload如下

%5Cimage%5CphpUnserialize%5C4.png

将出现的字符通过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文件中有一个Flag类,此外,我们可以用同样的方法得到index.php文件中的内容

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 "不能现在就给你flag哦";

exit();

}else{

include($file);

$password = unserialize($password);

echo $password;

}

}else{

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

}

?>

还原hitcon 2016一道web题(php反序列化漏洞)_诸神之眼的博客-爱代码爱编程

实验环境搭建:PHPstudy,火狐(backbar),notepad++; 原题目代码:https://github.com/orangetw/My-CTF-Web-Challenges/tree/master/hitcon-ctf-2016/babytrick 本人在还原此题目时,因为mysql数据库用户名密码和方便调试等原因对源码的一些参数做了一

php反序列化原理和案例演示_以菜之名的博客-爱代码爱编程

php反序列化原理和案例演示 一、序列化serialize() 序列化是把一个对象变成可以传输的字符串,例: class S{ public $test=“pikachu”; }

浅谈php反序列化漏洞原理_ting2909的博客-爱代码爱编程

序列化用途:方便于对象在网络中的传输和存储 1|10x01 php反序列化漏洞 在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。 常见的序列化格式: 二进制格式 字节数组 json

PHP反序列化漏洞原理与举例-爱代码爱编程

原理: 未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果。 在反序列化的过程中自动触发了某些魔术方法。 漏洞触发条件: unserialize函数的变量可控,php文件中存在可利用的类,类中有魔术方法 魔术方法: __construct()当一个对象创建时被调用 __destr

PHP反序列化漏洞——漏洞原理及防御措施-爱代码爱编程

序列化   将对象转换成字符串 反序列化 将特定格式的字符串转换成对象什么是反序列化漏洞 PHP反序列化漏洞也叫PHP对象注入,是一个非常常见的漏洞,这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常危险的后果。漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程

【PHP】反序列化漏洞(又名“PHP对象注入”)-爱代码爱编程

PHP对象注入(俗称反序列化漏洞) 相关函数漏洞成因漏洞利用进阶版之变量权限为私有或者保护总结 相关函数 在利用这个漏洞之前我们要先了解相关的函数都有什么,弱点在哪里 看不懂下面的不要紧 后面我会慢慢解释unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。返回的是转换之后的值,可为 integer、flo

PHP反序列化漏洞研究及原理-爱代码爱编程

前言: 反序列化是OWASP 2017中的一个比较大威胁的漏洞 而且一般安全类的问代码级的漏洞一般会问到这个,所以记录一下。 什么是反序列化? 首先引进两个函数,serialize(序列化函数)和unserialize(反序列化函数) 序列化与反序列化作用: 序列化: 对象转换为字符串的过程 这么讲可能有点晦涩难懂,上代码,看注释应该能看懂 (

php反序列漏洞 实例_PHP反序列化漏洞原理及示例-爱代码爱编程

文章目录 序列化与反序列化 PHP魔法函数 反序列化漏洞 简介 原理 触发条件 示例 PHP反序列化 PHP反序列化 序列化与反序列化 序列化说通俗点就是把一个对象变成可以传输的字符串。 序列化过程中还会对不同属性的变量进行不同方式的变化 public的属性在序列化时,直接显示属性名 protected的属性在序列化时,会在

php反序列化漏洞原理,PHP反序列化漏洞原理与复现-爱代码爱编程

php反序列化漏洞,又叫php对象注入漏洞 序列化与反序列化 serialize() 当在php中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,保存对象的值方便之后的传递与使用。测试代码如下; class chybeta{ var $test = '123'; } $class1 = new chybeta;

PHP反序列化漏洞原理浅谈-爱代码爱编程

序列化与反序列化 序列化就是指将数据结构或者对象状态转换成可取用的格式,以便在相同或者不同的计算机中进行数据的传输。 个人理解 就是将一个对象用一串字符表示出来用来进行通信和传输,一个类,里面包含很多方法和变量,不能直接以类这种格式进行传输,不然会传输很多的字符而且也不好识别。所以将类转换成一种固定的格式传输再进行逆向的转换这就是序列化与反序列化。