PHP序列化和反序列化

https://www.jianshu.com/p/8f498198fc3d
一篇通俗易懂的好文章:
https://www.freebuf.com/articles/web/167721.html
序列化和反序列化
序列化是把一个对象变成可以传输的字符串。
反序列化就是把那串可以传输的字符串再变回对象
1.序列化
serialize() 函数
用于序列化对象或数组,并返回一个字符串。可以用于保存


输出结果
a:3:{i:0; s:2:“t1”; i:1; s:3:“tt2”; i:2; s:4:“ttt3”; }
各个字符的意义 —> o表示对象,a表示数组,s表示字符,i表示数字
a:3 表示有三个数组
i:0,表示第一个数组,s:2:“t1”,表示第一个数组是字符,2表示有两个字符,为"t1"
i:1,表示第二个数组,s:3:“tt2”,表示第二个数组是字符,3表示有三个字符,为"tt2"
i:2,表示第三个数组,s:4:“ttt3”,表示第三个数组是字符,4表示有三个字符,为"ttt3"
2.反序列化
unserialize() 函数
用于将通过 serialize()函数序列化后的对象或数组进行反序列化,变成一个对象,并返回原始的对象结构

结果如下
Array ( [0] =>t1 [1] =>tt2 [2] =>ttt3 )

php使用serialize这个过程被称为序列化,使用unserialize这个过程被称为反序列化。
3.为什么会产生这个漏洞
那么,问题来了,这么序列化一下然后反序列化,为什么就能产生漏洞了呢?
这个时候,我们就要了解一下PHP里面的魔术方法了,魔法函数一般是以__开头,通常会因为某些条件而触发不用我们手动调用:
在研究反序列化漏洞的时候,碰见这几个魔法函数就要仔细研究研究了:
php类可能会包含一些特殊的函数叫magic函数(魔法函数),magic函数命名是以符号__开头的,比如 __construct, __destruct, __toString, __sleep, __wakeup等等。这些函数通常会因为某些条件而触发不用我们手动调用,例如
__construct()当一个对象创建时被调用__destruct()当一个对象销毁时被调用__toString()当一个对象被当作一个字符串使用__sleep() 在对象在被序列化之前运行__wakeup将在序列化之后立即被调用

这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。
举个别人的例子:
test; } } $a = $_GET['test']; $a_unser = unserialize($a); ?>

这里我们只要构造payload:
http://127.0.0.1/test.php?test=O:1:”A”:1:{s:4:”test”; s:5:”hello”; }

就能控制echo出的变量
攻防世界 unserialize3 PHP序列化和反序列化
文章图片

先来看看题目代码
class xctf{ public $flag = '111'; public function __wakeup(){ exit('bad requests'); } ?code=

知识点:1、serialize()函数:用于序列化对象或数组,并返回一个字符串。序列化对象后,可以很方便的将它传递给其他需要它的地方,且其类型和结构不会改变。2、unserialize()函数:用于将通过serialize()函数序列化后的对象或数组进行反序列化,并返回原始的对象结构。3、魔术方法:PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __ 为前缀。4、serialize()和unserialize()函数对魔术方法的处理:serialize()函数会检查类中是否存在一个魔术方法__sleep()。如果存在,该方法会先被调用,然后才执行序列化操作,此功能可以用于清理对象。 unserialize()函数会检查类中是否存在一个魔术方法__wakeup(),如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。5、__wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数,这也是一个绕过点。

结合题目和题中代码,就是让我们运用,__wakeup()函数的漏洞拿flag的
创建一个xctf类并对其进行序列化:

得到结果:O:4:“xctf”:1:{s:4:“flag”; s:3:“111”; }
大括号前面的1便是属性变量的个数,只需对其进行更改便可以绕过__wakeup(),使exit函数不被执行。
传参
?code=O:4:"xctf":2:{s:4:"flag"; s:3:"111"; }

【PHP序列化和反序列化】拿到flag

    推荐阅读