一、序列化
序列化(serialize)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区,之后可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
简单地说,就是将状态信息保存为字符串。例如,将PHP中的对象、类、数组、变量、匿名函数等转化为字符串,方便保存到数据库或者文件中。
反序列化: 序列化是将对象的状态信息转为字符串储存起来,反序列化就是将字符串转化为状态信息,即从新将状态信息拿出来使用。
二、函数解析
PHP中有一类特殊的方法叫“Magic function”魔术方法
__construct():当创建对象时会自动调用。但在unserialize()时不会自动调用的。(构造函数)
__wakeup() :使用了反序列化函数unserialize()时会自动调用。
__destruct():当对象被销毁时会自动调用。(析构函数)
#__FILE__是当前文件的绝对路径
#show_source()高亮显示当前文件的源码
#class是类,拥有属性、函数
#在PHP中创建一个对象后,可以通过serialize()把这个对象转变成一个字符串,保存对象的值方便之后的传递与使用
<meta charset='UTF-8' />
<?php
show_source(__FILE__);
echo "<br />";
class chybeta {
var $test;
function __construct(){
echo "__construct"; //对象创建的时候会触发
echo "<br />";
}
function __wakeup(){
echo "__wakeup"; //使用了反序列化函数的时候会触发
echo "<br />";
}
function __destruct(){
echo "__destruct"; //对象被销毁的时候会触发
echo "<br />";
}
function action(){
echo "运行action()函数,输出变量:";
var_dump($this->test);
echo "<br />";
}
}
$class1 = new chybeta; //新建一个对象
$class1->test = 'Love123456';
$class1->action();
$class1_ser = serialize($class1); //序列化
print_r($class1_ser); //输出序列化后的值
echo "<br />";
?>
输出:
O:Object对象,变量类型
7:类名长度,即类名有7个字符
chybeta:类名
1:只有一个值
s:string,表示字符串
4:表示test字符串的长度
#unserialize()可以从已存储的表示中创建PHP的值,单就本次环境而言,可以从序列化后的结果中恢复对象(object)
<meta charset='UTF-8' />
<?php
show_source(__FILE__);
echo "<br />";
class chybeta {
var $test;
function __construct(){
echo "__construct"; //对象创建的时候会触发
echo "<br />";
}
function __wakeup(){
echo "__wakeup"; //使用了反序列化函数的时候会触发
echo "<br />";
}
function __destruct(){
echo "__destruct"; //对象被销毁的时候会触发
echo "<br />";
}
function action(){
echo "运行action()函数,输出变量:";
var_dump($this->test);
echo "<br />";
}
}
$class2 = 'O:7:"chybeta":1:{s:4:"test";s:10:"Love123456";}';
$class2_unser = unserialize($class2);
$class2_unser->action();
print_r($class2_unser);
?>
输出:
本质上serialize()和unserialize()在PHP内部实现上是没有漏洞的,漏洞产生的主要原因是应用程序在处理对象、魔术函数以及序列化相关问题的时操作不当。
例如,当传给 unserialize() 的参数可控时,那么用户就可以注入精心构造的payload。同时,进行反序列化的时候有可能会触发对象中的一些魔术方法,造成意想不到的危害。