php的序列号与反序列化
0X00 序列化
serialize()函数将一个对象转换为字符串形式
我们来看一下直接输出对象是什么效果的:
1 |
|
效果如下:
这个时候我们利用serialize()函数将这个对象进行序列化成字符串然后输出,代码如下:
1 |
|
效果如下:
如果不是public方法那么后面的读取方法就有点不一样,例如代码如下:
1 |
|
效果如下 :
private分析:
这样就发现本来是age结果上面出现的是testage,而且testage长度为7,但是上面显示的是9。
查找资料后发现private属性序列化的时候格式是%00类名%00成员名,%00占一个字节长度,所以age加了类名后变成了testage长度为9。
protect分析:
本来是sex结果上面出现的是*sex,而且*sex的长度是4,但是上面显示的6。
查找资料后发现protect属性序列化的时候格式是%00%00成员名
这里介绍一下public、private、protect的区别
0X01 反序列化
定义:反序列化就是利用unseralize()函数将一个经过序列化的字符串还原成php代码形式。
代码如下:
1 |
|
0X02 反序列化漏洞原理
到这儿也许大家会想着序列化过去再反序列化回来,不就是形式之间的转换吗,和漏洞有什么关系?
这里先掌握php常见的魔术方法,先列出几个最常见的魔术方法。
CVE-2016-7124 __wakeup绕过
__wakeup 魔法函数简介
unserialize()会检查是否存在一个 __wakeup()方法。如果存在,则会先调用 __wakeup()方法,预先准备对象需要的资源。
反序列化时,如果表示对象属性个数的值大于真实的属性个数时就会跳过__wakeup()的执行。
漏洞影响版本
php5<5.6.25
php7<7.0.10
漏洞复现
代码如下:
1 |
|
魔法函数__wakeup()要比__destruct()先执行,所以我们传入
O:1:”A”:1:{s:6:”target”;s:18:”‘’;}
时会被先执行的__wakeup()函数$target赋值覆盖为wakeup!,然后生成的hello.php里面的内容就是wakeup!
传入?test=O:1:”A”:1:{s:6:”target”;s:18:”‘’;}
会返回:
hello.php
wakeup!
现在我们根据绕过方法:对象属性个数的值大于真实的属性个数时就会跳过__wakeup()的执行,对象个数原来是1我们将其改为2,也就是
?test=O:1:”A”:2:{s:6:”target”;s:18:”‘’;}
就能实现绕过。
0X03 xctf Web_php_unserialize
构造payload:?var=O:4:”Demo”:2:{s:10:”%00Demo%00file”;s:8:”f14g.php”}
先把%00进行一次url解码:
然后进行一次base64编码得到payload:
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
拿下flag
- 本文作者: y0lo
- 本文链接: http://example.com/2020/10/24/反序列化的学习/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!