什么是序列化?
- 序列化就是将对象转换为字符串,反序列化相反。序列化利于对象的保存和传输
serialize() //序列化函数
unserialize() //反序列化函数
<?php
class test
{
public $name = 'tesName';
}
$o = new test();
$s = serialize($o);
echo $s; //输出对象$o的序列化字符串
?>
O:4:"test":1:{s:4:"name";s:7:"tesName";}
- O 代表这是一个对象,还有可能出现a,a表示为数组
- 4 代表这个对象名长度为4
- test 是对象名称
- 1 表示这个对象的属性个数,这里为1
- s 表示属性数据类型,s为string,i为int
- name 表示属性名称
- s:7:"tesName" 整个表示属性的值
漏洞原理
- 未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
触发条件
- unserialize()的参数可控,这样我们才能够构造特定的序列化字符串
- 文件中存在可利用的类,类中有魔术方法
PHP常见魔术方法
__construct() //创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象中调用一个不可访问方法(经常是不存在的类)时触发
__get() //读取不可访问属性的值时触发
__set() //在给不可访问属性赋值时触发
__isset() //当对不可访问属性调用 isset() 或 empty() 时触发
__unset() //当对不可访问属性调用 unset() 时触发
__toString() //当一个类被当成字符串时触发,echo或者拼接字符串时都会触发
__invoke() //当尝试以调用函数的方式调用一个对象时触发
__sleep() //执行serialize()时,先会调用这个函数
__wakeup() //执行unserialize()时,先会调用这个函数
漏洞分类
无类问题
- 无类指的是不调用类来利用反序列化漏洞,通常是对序列化后的字符串进行有关字符上的操作
有类问题
- 有类指的是通过调用类中的魔术方法来利用反序列化漏洞,重点在于找到可利用的魔术方法(通常是好几个类的魔术方法构成一个利用链,和套娃差不多)