序列化和反序列化的定义:
序列化
是将一个对象转换为一个字符串的字节序列储存的过程
"O:6:"People":3:{s:4:"name";s:5:"error";s:3:"age";s:2:"20";s:3:"sex";s:1:"M";}"
可以看出,当序列化后输出的结果是一串字符。
O 表示object,一个对象
6 "People" 表示对象名长度为6,名为"People"
3 表示有3个属性
s 为"string"类型
4 为属性name的长度
7 为属性值error的长度
后面的内容以此类推,一个类的属性是以;N;
结尾,;}结束一串序列化字符。
序列化
最重要的作用
:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。反序列化
是将字符串(实例)转为对象的过程
反序列化
的最重要的作用:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。
PHP反序列化的原理
未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化进程,从而导致代码执行,SQL注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
PHP序列化与反序列化的关键函数:
serialize():将一个对象转换为字符
unserialize():将字符还原成一个对象
区分反序列化用到的技术有类与无类可以通过看是否有class,有即为有类,有类的地方就会有魔术方法
PHP中把两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用。
PHP 魔术方法的具体案例可以参考PHP手册—PHP Magic method
具体方法及案例
十六种魔术方法详解:
https://segmentfault.com/a/1190000007250604
- _ _construct():类的构造函数
在类中声明构造函数需要注意的事项
在同一个类中只能声明一个构造函数,原因是,PHP不支持构造函数重载
- _ _destruct():类的析构函数
一般来说,析构方法在PHP中并不很常用,它属类中可选择的一部分,通常用来完成一些在对象销毁前的清理任务。
- _ _call():在对象中调用一个不可访问方法时调用
- _ _callStatic():用静态方式中调用一个不可访问方法时调用
- _ _get():获得一个类的成员变量时调用
在PHP面向对象编程中,类的成员属性被定义为private后,如果我们试图在外面调用它则会出现“不可访问某个私有属性”的错误。那么为了解决这个问题,我们可以使用_ _get()。
_ _get的作用,在程序运行过程中,通过它可以在对象的外部获取私有成员的值
- _ _set():设置一个类的成员变量时调用
- _ _isset():当不可访问属性调用isset()或empty()时调用
- _ _unset():当对不可访问属性调用unset()时被调用
- _ _sleep():执行serialize()时,先会调用这个函数
- _ _wakeup(): 执行unserialize时,先会调用这个函数
- _ _toString():类被当成字符串时的回应方法
- _ _invoke():调用函数的方式调用一个对象时的回应方法
- _ _set_state():调用var_export()导出类时,此静态方法会被调用
- _ _clone():当对象复制完成时调用
- _ _dutoload():尝试加载未定义的类
- _ _debugInfo:打印所需调试信息
靶场训练