Loading... <div class="tip share">请注意,本文编写于 2039 天前,最后修改于 1989 天前,其中某些信息可能已经过时。</div> ###序列化对象 - 在会话中存放对象 所有php里面的值都可以使用函数`serialize()`来返回一个包含字节流的字符串来表示。`unserialize()`函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。 为了能够`unserialize()`一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。 如果要想在另外一个文件中解序列化一个对象,这个对象的类必须在解序列化之前定义,可以通过包含一个定义该类的文件或使用函数`spl_autoload_register()`来实现。 上面是官方文档中对序列化的解释。简单来说,序列化就是将一个类中的所有变量保存在一个字符串中。那么反序列化当然就是把这个字符串转化为类啦~(前提是这个类已经定义了: D) ###一个小例子 网上随便找的例子: <div class="panel panel-default collapse-panel box-shadow-wrap-lg"><div class="panel-heading panel-collapse" data-toggle="collapse" data-target="#collapse-baed45bfc2974a64e22b6f2b7ffe0eaf48" aria-expanded="true"><div class="accordion-toggle"><span style="">源码</span> <i class="pull-right fontello icon-fw fontello-angle-right"></i> </div> </div> <div class="panel-body collapse-panel-body"> <div id="collapse-baed45bfc2974a64e22b6f2b7ffe0eaf48" class="collapse collapse-content"><p></p> ```php <?php class chybeta{ var $test = '123'; } $class1 = new chybeta; $class1_ser = serialize($class1); print_r($class1_ser); ?> ``` <p></p></div></div></div> 上面的源码输出如下: ``` O:7:"chybeta":1:{s:4:"test";s:3:"123";} ``` 下面就逐个解释这些都是什么意思吧。 - `O` 代表储存的是一个对象(object) - `7` 表示对象的名称有7个字符。 - `"chybeta"` 表示对象的名称。 - `1` 表示有一个值。 - `{s:4:"test";s:3:"123";}` 中: - `s` 表示字符串 - `4` 表示该字符串的长度 - `"test"` 为字符串的名称,之后的类似。 > 这里提示一下:序列化的时候会调用 `__sleep()` 这个函数,反序列化的时候会调用 `__wakeup()` 这个函数。(如果有的话) !> 如果对象中含有私有成员的话,序列化出来的成员名会包含两个空字符。举例如下: <div class="panel panel-default collapse-panel box-shadow-wrap-lg"><div class="panel-heading panel-collapse" data-toggle="collapse" data-target="#collapse-23201fa06d44fc144f25cef4780bfd8063" aria-expanded="true"><div class="accordion-toggle"><span style="">源码</span> <i class="pull-right fontello icon-fw fontello-angle-right"></i> </div> </div> <div class="panel-body collapse-panel-body"> <div id="collapse-23201fa06d44fc144f25cef4780bfd8063" class="collapse collapse-content"><p></p> ```php <?php class test { private $flag = "flag{233}"; public $a = "aaa"; static $b = "bbb"; } $test = new test; $data = serialize($test); echo $data; ?> ``` <p></p></div></div></div> <div class="panel panel-default collapse-panel box-shadow-wrap-lg"><div class="panel-heading panel-collapse" data-toggle="collapse" data-target="#collapse-524010b5b74cc6fba92282e0c73684a44" aria-expanded="true"><div class="accordion-toggle"><span style="">运行结果</span> <i class="pull-right fontello icon-fw fontello-angle-right"></i> </div> </div> <div class="panel-body collapse-panel-body"> <div id="collapse-524010b5b74cc6fba92282e0c73684a44" class="collapse in collapse-content"><p></p> ``` O:4:"test":2:{s:10:"testflag";s:9:"flag{233}";s:1:"a";s:3:"aaa";} ``` <p></p></div></div></div> 可以看到 `flag` 成员的名称长度为 10 。转换成文件可以看到 `test` 两边有两个空字符。 ###补充 在一次内部赛的时候碰到的知识点: 漏洞有效的PHP版本未知。我本地环境用的是PHP5.4 。PHP在反序列化对象的时候,会先检测 `O:` ,然后再检测是否有 `+` 。如果是 `+` 的话就忽略 `+` 继续检测后面的数字。这就导致了可以绕过一些 waf 如 `/O:\d/` 之类的正则。 参考资料:http://sec-redclub.com/archives/962/ 最后修改:2019 年 06 月 12 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏