

在了解反序列化漏洞之前,先了解一下php中的序列化。 php中的序列化和反序列化都是通过函数来实现的:
序列化(serialize):序列化是将对象的状态信息转换为可保存或传输的字符串的过程 反序列化(unserialize):反序列划就是将字符串转换为对象原本的状态信息。

以上代码,就是进行序列化的处理 其中:

以上代码,就是进行反序列化的处理。 从序列化后的结果中恢复对象的状态信息 test类中有一个变量index内容是xxba
本质上serialize()和unserialize()在PHP内部实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。 当传递给unserialize()的参数可控时,那么攻击者就可以注入payload,当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
php中的魔术方法有很多,如__construct()、__destruct()、 __call() 、__callStatic()、__get()、__set()、__isset()等 主要关注一下几个:

代码执行解析:

打开靶场之后,发现就是一个简单的页面,进入flag.php发现页面是空的,没有任何东西。 那么就只能将这个页面源码 解析一下了,首先看到第一个方法有两个下划线,这里可能是魔术方法,搜索一下,果然是魔术方法。

具体用途是当一个对象被当作字符串对待的时候,会触发这个魔术方法 highlight_file是对文件进行语法高亮显示。



php代码部分解读完毕,其实只有一处能为我们所用,就是第二个判断语句,这样会继续向下执行。 因为在最下面还有一串foreach,所以需要代码执行到最下面,能够满足的只有第二个if语句。

这里就是循环遍历数组,输出反序列化后的对象。 接下来就要想办法让flag.php的内容输出出来,这里就可以利用反序列化,找到反序列化代码段、可控制的点。

这个点很明显就能够满足,我们能够控制cookie传参。 将源码前半段复制到本地,使其进行序列化,但是因为遍历需要是数组才能遍历,所以在发序列化的时候就直接加上一个数组

本地访问,得到序列化后的结果。 当数组遍历的时候会进入__tostring()方法,会输出readme.txt和传递进去的值,因为这里传递的是flag.php所以就会输出flag.php的值。 得到了序列化之后的结果,就需要满足第二个if中的条件,md5(m)=h。
那么将序列化之后的结果进行md5加密:e2d4f7dcc43ee1db7f69e76303d0105c
然后拼接上序列化之后的结果.就是
e2d4f7dcc43ee1db7f69e76303d0105ca:1:{i:0;O:6:“readme”:1:{s:6:“source”;s:8:“flag.php”;}}
但是因为cookie要经过url,所以需要将这一串字符串url编码一下。
e2d4f7dcc43ee1db7f69e76303d0105ca%3A1%3A%7Bi%3A0%3BO%3A6%3A%22readme%22%3A1%3A%7Bs%3A6%3A%22source%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D