php序列化与反序列化
前言
最近在总结php序列化相关的知识,看了好多网上的文章,现在将自己的理解记录下来。
php序列化与反序列化基础
序列化与反序列化
- 序列化是将变量转换为可保存或可传输的字符串的过程。
- 反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。
php序列化与反序列化函数
- serialize():可以将变量转换为字符串并且在转换中可以保存当前变量的值。
- unserialize():可以将serialize()生成的字符串转化为变量。
- php进行序列化的目的就是保存一个对象方便以后重用。
php序列化实例
1 | <?php |
运行结果:O:6:"Person":2:{s:4:"name";s:2:"Lv";s:3:"age";i:18;}
这里的O
代表存储的是对象(object),假如你给serialize()
传入的是一个数组,那它会变成字母a
。7
表示对象的名称有7个字符。"chybeta"
表示对象的名称。1
表示有一个值。{s:4:"test";s:3:"123";}
中,s
表示字符串,4
表示该字符串的长度,"test"
为字符串的名称,之后的类似。
- serialize():序列化一个对象将会保存对象的所有变量,但不会保存对象的方法,只会保存类的名字。
php反序列化实例
1 | <?php |
运行结果:
1 | Person Object |
- unserialize():unserialize()一个对象,这个对象的类必须已经定义过。
php魔法函数
php类中包含了一些魔法函数,这些函数可以在脚本的任何地方不用声明就可以使用。
- __construct() // 当一个对象创建时被调用
- __destruct() // 对象被销毁时触发
- __wakeup() // 使用unserialize时触发
- __sleep() // 使用serialize时触发
- __toString() // 把类当作字符串使用时触发
- __get() // 用于从不可访问的属性读取数据
反序列化漏洞
由前面可以看出,当传给 unserialize() 的参数可控时,我们可以通过传入一个精心构造的序列化字符串,从而控制对象内部的变量甚至是函数。
下面是我在本地搭建的环境。
php反序列化漏洞demo1
- test1.php:
1 | <?php |
在test1.php
中可以看到,delete类中定义了一个__destruct()
函数,该函数中会执行删除文件的操作。如果我们想利用该类来执行任意文件的删除操作,则需要寻找到一个可控的unserialize()
函数
- test2.php:
1 | <?php |
在test2.php
中包含了test1.php
,并且我们可以看到$per = unserialize($_GET['per_serialized']);
,其中per_serialized
是可控的。
如果我们已经知道在该目录下有一个1.txt
文件,如果我们想要删除这个文件,则可以这样构造poc:
1 | <?php |
可以得到payload为:O:6:"delete":1:{s:8:"filename";s:5:"1.txt";}
。
访问:http://127.0.0.1/test2.php?per_serialized=O:6:%22delete%22:1:{s:8:%22filename%22;s:5:%221.txt%22;}
php反序列化漏洞demo2
- test4.php:
1 | <?php |
在test4.php
中可以看到,类中定义了一个__toString()
函数,该函数可以返回一个文件内容。如果我们想利用该类来读取任意文件,不仅需要寻找一个可利用的unserialize
,还要有一个触发toString()
函数的条件。
- test5.php
1 | <?php |
在test5.php
中,包含了test4.php
。可以看到$per = unserialize($__GET['per_serialized']);
,其中per_serialized
可控。echo $per;
会触发__toString()
函数
构造poc,得到payload:
1 | <?php |
payload:O:4:"read":1:{s:8:"filename";s:5:"1.txt";}
访问:http://127.0.0.1/test5.php?per_serialized=O:4:%22read%22:1:{s:8:%22filename%22;s:5:%222.txt%22;}
总结
通过上面的学习,我们知道,要想找到一个php漏洞,需要先找到可控的反序列化函数,通过这些反序列化函数,我们去调用一些类,这些类中可能会包含一些魔法函数,在这些魔法函数中可能会有一些我们可控的危险操作,从而触发了php反序列化漏洞。