PHP中的序列化serialize()与反序列化unserialize()
0×00 PHP中的序列化与反序列化
序列化:是将对象的状态信息转换为可以存储或传输的形式的过程
反序列化:把字节序列还原为对象的过程称为反序列化。
0×01 序列化与反序列化的作用
序列化的存在是为了使对象可以以某种形式存储,和进行网络传输,使程序更具维护性。
因为跨平台存储和进行网络传输支持的数据格式是字节数组,因此我们需要通过一种特定的规则将对象转换成字节数组,这个规则就是序列化,而通过这个规则还原对象的过程就是反序列化。
就好比将一个搭建好的大型积木打乱的过程是序列化,这个过程使我们能够将打乱后的积木块放在盒子中,方便携带积木、存放积木并将积木进行转移(将对象从一个地方传递到另一个地方),而将打乱的积木重新搭建好的过程就是反序列化。
0×02 序列化格式
1 |
|
格式:
对象类型 : 对象名长度 : “对象名” : 对象成员变量个数 : { 变量1类型 : 变量名1长度 : 变量名1 ; 参数1类型 : 参数1长度 : 参数1 ; 变量2类型 : 变量名2长度 : “变量名2” ; 参数2类型 : 参数2长度 : 参数2 ; … … }
对象\变量\参数类型:1
2
3
4
5
6
7
8
9
10
11
12O - Class
a - Array
s - string
i - int
b - boolean
d - double
o - common object
r - reference
C - custom object
N - null
R - pointer reference
U - unicode string
序列符号:参数与变量之间用分号(;)隔开,同一变量和同一参数之间的数据用冒号(:)隔开。
0×03 反序列化漏洞成因
PHP反序列化漏洞又称PHP对象注入,是因为程序对输入数据处理不当导致的。漏洞的根源在于unserialize()函数的参数可控。如果反序列化对象中存在魔术方法,而且魔术方法中的代码或变量用户可控,就可能产生反序列化漏洞,根据反序列化后不同的代码可以导致各种攻击,如代码注入、SQL注入、目录遍历等等。
0×04 魔术方法(Magic methods)
PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法
1 | __construct() 类的构造函数,在对象创建时自动调用 |
0×05 魔术方法的触发
sleep() 和 wakeup()
serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。
与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 _ _wakeup() 方法
1 | <?php |
__toString()
__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。
1 | <?php |
__invoke()
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
1 | <?php |
学习链接:PHP之十六个魔术方法详解