什么是序列化和反序列化?
PHP序列化和反序列化是将数据从PHP对象或数组转换为字符串以在文件或网络中传输,然后将字符串转换回原始数据类型的过程。PHP序列化是通用数据交换格式,常用于Web应用程序中的数据存储和传输。
序列化的概念:
序列化:将php的对象或数组转换成字符串。
使用函数:serialize()
简单的序列化输出:
举例详解:
首先我们class定义一个类stu学生
public
表示这个类中有那些对象具有可见性和公开性,他表示这个类中的所有对象都具有公共可见性还表示一种控制访问的级别,就是任何成员可以直接访问不需要继承或使用权限
new:
创建一个新对象,并且调用类的构造函数
创建stu这个对象将他赋值给变量$stu1,可以通过访问$stu这个对象来调用和修改stu
中的参数和属性。
->:
操作符访问对象的属性
举例说明一下$stu1->name = "xiu",上面将stu赋值给了$stu1操作符可以访问stu中的name属性并将其设置为xiu进行输出
var_dump:
正常输出这个类型;
<hr>
html的标签添加一个水平分割线
echo:
输出serialize将输出对象进行序列化处理
代码源码:
<?
class stu{
public $name;
public $age;
public $sex;
public $score;
}
$stu1-> = new stu();
$stu1->name = "xiu";
$stu1->age = 18;
$stu1->sex = true;
var_dump($stu1);
echo"<hr/>";
echo serialize($stu1);
?>
反序列化:
反序列化:将字符串转换成php的对象或数组。
使用函数:unserialize()
这里我们用上面的举例。
$a
定义一个变量他的参数是序列化以后的字符串。
$person = unserialize($a);
将$a这个反序列化进行反推得到字符串,并且将字符串书写进入$person这个变量当中。
var_dump;
将这个变量输出并且显示出所属类型。
源码
<?
$a='序列化内容';
$person = unserialize($a);
var_dump($person);
?>
序列化与反序列化漏洞:
首先序列化与反序列化本身存在的意义是为了让数据传输更加快捷,稳定,安全。
但是在序列化与反序列化的转化过程中会触发某些魔术方法,利用这些模式方法会在成一些逻辑漏洞
使用__sleep这个魔术方法触发计算器。
__sleep()在使用序列化时触发;
源码
<?php
class animal{
public $name;
public $age;
public function __sleep(){
if(@$_GET['cmd']=="xiu"){
system('calc');
}
}
}
$an1= new animal;
$an1->name="dog";
$an1->age=3;
serialize($an1);
?>
代码解析
首先定义一个名为 animal 的类,
其中包含两个公共属性 $name 和 $age,以及一个名为 __sleep 的魔术方法。
当animal的对象被序列化时,__sleep() 方法会自动调用。
当被调用时IF会做出判断,如果检测到 GET 变量 cmd 的值等于 xiu,则会调用系统命令执行器打开 Windows 计算器应用程序,从而导致远程代码执行攻击。
效果展示:
php的常见魔术方法以及解释:
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__construct() //创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发