序列化与反序列化
在PHP中,序列化是将对象的状态转换为字符串的过程,反序列化则是将该字符串转化为原始的对象状态。
为什么传输对象需要进行序列化与反序列化?
答:对象的传递往往需要将对象序列化为字符串后再传递,主要有以下几个原因:
-
跨平台传输:不同的应用程序和平台可能使用不同的编程语言和数据结构,对象的直接传递可能会出现不兼容的问题。将对象序列化为通用的字符串格式能够解决这个问题,保证在跨平台和跨语言的情况下依然能正确传输对象数据。
-
减轻网络传输压力:对象直接传递需要传输的数据量较大,可能会给网络带来很大的压力。将对象序列化成字符串的方式能够大大减小传输的数据量,降低网络传输压力。
-
支持分布式技术:在分布式系统中,往往需要将服务调用请求传递到其他的服务器上,但是直接将对象传递过去是不现实的。序列化为字符串后再进行传递可以让不同的服务器之间共享对象数据和方法调用,提高系统的可扩展性和可用性。
总之,将对象序列化为字符串后再进行传递,能够降低网络传输压力并且使得对象能够跨语言和跨平台传输。
序列化与反序列化函数
serialize(); 将对象序列化成字符串
unserialize(); 将字符串反序列化回对象
什么是类、属性、方法、对象
类(Class)是一种面向对象编程的基本概念,用于描述具有相同属性和方法的对象类型。类定义了一个对象的结构,包括了属性(成员变量)和方法(成员函数)等内容。类是抽象的概念,不能直接使用。只有通过实例化(创建对象)才可以使用。
属性(Attribute/Property/Member Variable)是类中的一个成员变量,是类的某种特征或状态的描述,例如,一个人类的属性可能包括姓名、性别、年龄等。每个对象都有一组属性,它们描述了对象的状态。
对象(Object)是由类定义的一个实例,是类的具体实现,可以理解为类的一个具体的个体。实例化(Instantiation)是创建对象的过程,它需要使用 new 关键字来调用类的构造函数,并返回一个新的实例。
方法(Method)是一个类或对象中定义的函数,描述了对象的一些操作和功能,例如,一个人类可能有“说话”、“行走”、“工作”等方法。通过调用对象的方法,可以完成对对象的一些特定的操作或过程。
创建类:
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 中的魔术方法。
类中的魔术方法,在特定情况下会自动调用。即使魔术方法在类中没有被定义,也是真实存在的。
两个下划线
__construct() 在创建对象时自动调用
__destruct() 在销毁对象时自动调用
__wakeup() unserialize()时会自动调用这个函数
__sleep() serialize()时会自动调用这个函数
例子:
<?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;
//var_dump($an1);
@serialize($an1);
?>
什么是反序列化漏洞?
序列化和反序列化本身是为了实现数据在网络上完整高效的传输,但是由于反序列化过程中,对象的魔术方法会自动调用,魔术方法本身调用了别的方法,最终呈现一种链式调用,直到执行任意的代码或者命令,
修改序列化后的数据,目的是什么?
为了满足一定的条件以后实现链式调用
利用反序列化漏洞的必要条件:
1、代码中要存在危险函数。
2、代码中要存在反序列化入口。
3、满足一定条件下,通过链式调用至危险函数。