概念※
PHP中的序列化是指,将复杂的数据类型,转换成可以传输的字符串,反序列化就是将这个过程还原回原数据的方法。
PHP中,使用函数serialize()函数进行序列化操作。通过unserialize()进行还原操作
序列化后的结果※
经过序列化后,会得到一串字符串,其按照规定的格式编写:
基础格式如下:
[变量类型/o/a/s/i] : [长度] : [内容]对象(Object)序列化格式※
O:<类的名字的长度>:"类的名字":"属性个数":{<属性1名>;<属性1值>;...}示例:
class xctf{
public $flag = '111'; // 定义一个属性
public function __wakeup(){
exit('bad requests');
}
}在上述例中,定义了一个xctf类,内部有一个属性,属性名为flag,值为111
因此可以获得,类的名称长度为4类的名字为"xctf"
只有一个属性为flag 因此属性个数为1
在属性中 属性1的名字是 flag 为字符串 值为 111 同为字符串
整合格式
O:<类的名字的长度>:"类的名字":"属性个数":{<属性1名>;<属性1值>;...}得到
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
数值(interger)的序列化格式※
i : 值字符串(String)序列化格式※
字符的序列化后的格式比较简单,格式如下:
s : <字符串长度> : "字符串内容"
数组(Array)序列化格式※
数组序列化后格式如下
a:<数组中元素个数>:{<键1>;<值1>;....}其中,键和值 都遵循序列化的要求,如果为字符串则会变为字符串序列化后的结果,
特性(魔术方法)※
与python类似,有一些__开头的隐藏函数,在序列化函数执行的时候的时候会执行
__construct() //当一个对象创建时被调用
__destruct() //当一个对象被销毁时会触发
__wakeup() //使用反序列化的时候会触发
__sleep() //使用序列化函数的时候会触发
__toString() //当把类当做字符串的时候会触发
__get() //从不可访问的属性读取数据
__set() //将数据写入不可访问的属性
绕过某个函数※
__wakeup()函数※
当序列化后的结果,在进行反序列化过程中,会触发该函数,但当声明的属性个数大于实际提供的属性个数时,该函数就会跳过。
比如:
class xctf{
public $flag = '111'; // 假设真实flag在实际环境中
public function __wakeup(){
exit('bad requests'); // 反序列化时会触发,导致程序退出
}
}这个类中,属性只有1个,因此序列化后的结果为:
o:4:"xctf":1:{s:4:"flag";s:3:"111"}当我们把其中的1改为2,他就会大于后面实际给出的属性。
o:4:"xctf":2:{s:4:"flag";s:3:"111"}达到越过的目的