定义
序列化(串行化):定制小程序开发是将变量转换为可保存定制小程序开发或传输的字符串的过程;
(反串行化):定制小程序开发就是在适当的时候把这定制小程序开发个字符串再转化成原来定制小程序开发的变量使用;
定制小程序开发这两个过程结合起来,定制小程序开发可以轻松地存储和传输数据,使程序更具维护性;
常见的php序列化和反序列化方式主要有:serialize,unserialize
关于php面向对象编程:
对象:可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。
类:一个共享相同结构和行为的对象的集合。
每个类的定义都以关键字class开头,后面跟着类的名字。一个类可以包含有属于自己的变量,变量(称为“属性”)以及函数(“称为方法”)。类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号“_”开头的,比如_sleep,_wakeup等。这些函数在某些情况下会自动调用,比如:_construct当一个对象创建时调用(constructor);_destruct当一个对象被销毁时调用(destructor);_toString当一个对象被当作一个字符串时使用。
创建一个简单的PHP对象:
- <?php
- class TestClass
- {
- //一个变量
- public $variable = 'This is a string';
- //一个简单的方法
- public function PrintVariable()
- {
- echo $this->variable;
- }
- }
- //创建一个对象
- $object = new TestClass();
- //调用一个方法
- $object->PrintVariable();
- ?>
- //test.php
运行结果:
序列化可以将变量转换为字符串,并且在转换的过程中可以保存当前变量的值
反序列化可以将序列化生成的字符串转换回变量。
通俗来说:通过反序列化在特定条件下可以重建php对象并执行php对象中某些magic函数。
__sleep magic方法在一个对象被序列化时调用,__wakeup magic方法在一个对象被反序列化时调用。
存在漏洞的思路:一个类用于临时将日志储存进某个文件,当__destruct被调用时,日志文件将会被删除。
反序列化中常见的魔术方法
- __construct(),类的构造函数
- __destruct(),类的析构函数
- __call(),在对象中调用一个不可访问方法时调用
- __callStatic(),用静态方式中调用一个不可访问方法时调用
- __get(),获得一个类的成员变量时调用
- __set(),设置一个类的成员变量时调用
- __isset(),当对不可访问属性调用isset()或empty()时调用
- __unset(),当对不可访问属性调用unset()时被调用
- __sleep(),执行serialize()时,先会调用这个函数
- __wakeup(),执行unserialize()时,先会调用这个函数
- __toString(),类被当成字符串时的回应方法
- __invoke(),调用函数的方式调用一个对象时的回应方法
- __set_state(),调用var_export()导出类时,此静态方法会被调用
- __clone(),当对象复制完成时调用
- __autoload(),尝试加载未定义的类
- __debugInfo(),打印所需调试信息
反序列化绕过
protected和private绕过
如果变量前是protected,则是\x00*\x00类名的形式
如果变量前是private,则是\x00类名\x00的形式
绕过:
①:php7.1+反序列化对类属性不敏感,将protected改成public
②:手动将序列化后的形式改为protected或者private的标准形式,结合urlencode和base64编码进行操作
__wakeup绕过
原理:
当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup 的执行
示例:O:4:"Dino":1:{s:1:"a";s:4:"misc";}
改为O:4:"Dino":2:{s:1:"a";s:4:"misc";}
引用
通过值的引用可以使$a的值与$b的值相等
利用16进制绕过字符过滤
序列化结果:
O:4:"Dino":1:{s:3:"way";s:3:"web";}
中含有字符web,但将s改成S后,O:4:"Dino":1:{S:3:"\\77ay";s:3:"web";}
利用十六进制绕过了字符的过滤检测
同名方法的利用
POP链:
POP链利用: