PHP反序列化
目录
警告
本文最后更新于 2023-01-29,文中内容可能已过时。
要比赛了 来不及学了 把之前写了一半的贴上来吧
序列化与反序列化
访问控制符
访问控制符 | 效果 |
---|---|
Public | (属性或者方法)可以在当前类的内部访问,也可以在类的外部访问。 |
Protected | %00*%00属性名,所修饰的内容只能在类的内部访问 |
Private | %00类名%00属性名 |
%00为空白符,空字符也有长度,一个空字符长度为11
反序列化漏洞
魔术方法
魔术方法 | 调用方式 |
---|---|
__construct() | 实例化对象(new)时被调用, 当_ construct和以类名为函数名的函数同时存在时, _ construct将被调用,另一个不被调用。 |
__destruct() | 当删除一个对象(反序列化)或对象操作终止时被调用。 |
__toString() | 打印一个对象的时被调用。如echo obj;或printobj;或printobj; |
__sleep() | serialize之前被调用。若对象比较大,想删减一点东东再序列化,可考虑一下此函数。 |
__wakeup() | unserialize时被调用,做些对象的初始化工作。 |
__invoke() | 当脚本尝试将类调用为函数时触发 |
__call() | 对象调用某个方法, 若方法存在,则直接调用;若不存在,则会去调用__call函数。 |
__get() | 读取一个对象的属性时,若属性存在,则直接返回属性值; 若不存在,则会调用__get函数。 |
__set() | 设置一个对象的属性时, 若属性存在,则直接赋值; 若不存在,则会调用__set函数。 |
__clone() | 克隆对象时被调用。如:t=newTest();t=newTest();t1=clone $t; |
__isset() | 检测一个对象的属性是否存在时被调用。如:isset($c->name)。 |
__unset() | unset一个对象的属性时被调用。如:unset($c->name)。 |
__set_state() | 调用var_export时,被调用。用__set_state的返回值做为var_export的返回值。 |
__autoload() | 实例化一个对象时,如果对应的类不存在,则该方法被调用。 |
__wakeup绕过
当序列化字符串表示对象属性个数的数字值大于真实类中属性的个数时就会跳过_wakeup的执行。
版本要求: PHP5 < 5.6.25 PHP7 < 7.0.10
例题
POP链
概念
通过用户可控的反序列化操作,其中可触发的魔术方法为出发点,在魔术方法中的函数在其他类中存在同名函数,或通过传递,关联等可以调用的其他执行敏感操作的函数,然后传递参数执行敏感操作,即
用户可控反序列化→魔术方法→魔术方法中调用的其他函数→同名函数或通过传递可调用的函数→敏感操作