简单记录一下反序列化
0x00 什么是序列化
在PHP中右serialize()
和unserialize()
两个函数,php里面的值都可以使用函数serialize()
来返回一个包含字节流的字符串来表示。unserialize()
函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。
0x01 example
简单的一个例子
<?php //序列化示例 //student类 class student{ public $name = "DYBOY"; public $sex = "boy"; public function getInfo(){ echo $this->$name; } } //实例化一个student对象 $person = new student(); //调用方法 $person->getInfo(); ?>
访问得到如下结果:
这就是一个正常的例子
但是,在PHP中有一些魔术方法,会自动调用,比如常见的 __construct()
,__destruct()
,__toString()
等等,下面修改上面的example得到如下代码:
<?php <?php //序列化示例 class student{ public $name = "DYBOY"; public $sex = "boy"; public function getInfo(){ echo $this->name; echo "<br/>"; } public function __construct(){ echo "对象被建立<br/>"; } public function __destruct(){ echo "对象被销毁<br/>"; } public function __toString(){ return "当对象当作字符串输出时调用<br/>"; } } $person = new student(); $person->getInfo(); echo $person; //对象当作字符串输出 ?>
总结几个常见魔术函数:
__wakeup() //使用unserialize时触发 __sleep() //使用serialize时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __toString() //把类当作字符串使用时触发,返回值需要为字符串 __invoke() //当脚本尝试将对象调用为函数时触发 `
0x02 序列化
//接着上面的代码 echo serialize($person); //输出:O:7:"student":2:{s:4:"name";s:5:"DYBOY";s:3:"sex";s:3:"boy";} echo unserialize($ser); //输出:当对象当作字符串输出时调用 对象被销毁
字母类型解释:
a - array b - boolean d - double i - integer o - common object r - reference s - string C - custom object O - class N - null R - pointer reference U - unicode string
0x03 漏洞利用
原因:当使用反序列化时,如果魔术函数当中的参数时可控的,那么就能够造成XSS或着其他的漏洞
漏洞CTF参考题目:神盾局的秘密
*参考文章:http://www.lmxspace.com/2018/05/03/php-unserialize-%E5%88%9D%E8%AF%86/
版权声明:《 PHP反序列化深入理解 》为DYBOY原创文章,转载请注明出处!
最后编辑:2018-6-18 15:06:38