参考:http://t.csdn.cn/dWy9l
https://www.cnblogs.com/fish-pompom/p/11126473.html
序列化
有时需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串,等到达另一端时,再还原为原来的对象,这个过程称之为串行化 (也叫序列化)。
json 数据使用,分隔开,数据内使用:分隔键和值
json 数据其实就是个数组,这样做的目的也是为了方便在前后端传输数据,后端接受到 json 数据,可以通过 json_decode () 得到原数据,这种将原本的数据通过某种手段进行 "压缩",并且按照一定的格式存储的过程就可以称之为序列化。
有两种情况必须把对象序列化:
把一个对象在网络中传输
把对象写入文件或数据库
1 2 3 public:属性被序列化的时候属性值会变成 属性名 protected:属性被序列化的时候属性值会变成 \x00*\x00属性名 private:属性被序列化的时候属性值会变成 \x00类名\x00属性名
ps: \x00 表示空字符,但是还是占用一个字符位置(空格)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php class People{ public $id; protected $gender; private $age; public function __construct(){ $this->id = 'Hardworking666'; $this->gender = 'male'; $this->age = '18'; } } $a = new People(); echo serialize($a); ?>
1 O:6:"People":3:{s:2:"id";s:14:"Hardworking666";s:9:" * gender";s:4:"male";s:11:" People age";s:2:"18";}
1 2 3 4 5 6 7 8 9 10 11 12 13 a - array 数组型 b - boolean 布尔型 d - double 浮点型 i - integer 整数型 o - common object 共同对象 r - objec reference 对象引用 s - non-escaped binary string 非转义的二进制字符串 S - escaped binary string 转义的二进制字符串 C - custom object 自定义对象 O - class 对象 N - null 空 R - pointer reference 指针引用 U - unicode string Unicode 编码的字符串
ps: 请记住,序列化他只序列化属性,不序列化方法
在反序列化的时候一定要保证在当前的作用域环境下有该类存在
反序列化攻击的时候也就是依托类属性进行攻击
反序列化
被序列化的字符串还原为对象,然后在接下来的代码中继续使用。
1 2 $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}"); echo $u->test; //得到的结果为pikachu
反序列化漏洞
序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了 PHP 中的魔法函数,就会导致安全问题
具备反序列化漏洞的前提:
必须有 unserailize () 函数
unserailize () 函数的参数必须可控(为了成功达到控制你输入的参数所实现的功能,可能需要绕过一些魔法函数
魔法函数
PHP 将所有以 __
(两个下划线)开头的类方法保留为魔术方法。所以在定义类方法时,除了上述魔术方法,建议不要以 __
为前缀。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 __construct(),类的构造函数 __destruct(),类的析构函数 __call(),在对象中调用一个不可访问方法时调用 __callStatic(),用静态方式中调用一个不可访问方法时调用 __get(),获得一个类的成员变量时调用 __set(),设置一个类的成员变量时调用 __isset(),当对不可访问属性调用isset()或empty()时调用 __unset(),当对不可访问属性调用unset()时被调用。 __sleep(),执行serialize()时,先会调用这个函数 __wakeup(),执行unserialize()时,先会调用这个函数 __toString(),类被当成字符串时的回应方法 __invoke(),调用函数的方式调用一个对象时的回应方法 __set_state(),调用var_export()导出类时,此静态方法会被调用。 __clone(),当对象复制完成时调用 __autoload(),尝试加载未定义的类 __debugInfo(),打印所需调试信息
1 2 3 4 5 6 7 8 9 10 11 12 13 __construct:构造函数,当一个对象创建时调用 __destruct:析构函数,当一个对象被销毁时调用 __toString:当一个对象被当作一个字符串时使用 __sleep:在对象序列化的时候调用 __wakeup:对象重新醒来,即由二进制串重新组成一个对象的时候(在一个对象被反序列化时调用) 从序列化到反序列化这几个函数的执行过程是: __construct() ->__sleep() -> __wakeup() -> __toString() -> __destruct()
__
toString () 这个魔术方法能触发的因素
1 2 3 4 5 6 7 8 1. echo($obj)/print($obj)打印时会触发 2. 反序列化对象与字符串连接时 3. 反序列化对象参与格式化字符串时 4. 反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型) 5. 反序列化对象参与格式化SQL语句,绑定参数时 6. 反序列化对象在经过php字符串处理函数,如strlen()、strops()、strcmp()、addslashes()等 7. 在in_array()方法中,第一个参数时反序列化对象,第二个参数的数组中有__toString()返回的字符串的时候__toString()会被调用 8. 反序列化的对象作为class_exists()的参数的时候
利用
结合 xss
O:1:“S”:1:{s:4:“test”;s:29:“”;}
根据具体的魔法函数,获取想要的内容
还是根据后面的 ctf 题实操吧