触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法: 参考:https://www.cnblogs.com/20175211lyz/p/11403397.html __construct()//创建对象时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __invoke() //当脚本尝试将对象调用为函数时触发
本地代码示例
<?php class ABC{ public $test; function __construct(){ $test =1; echo '调用了构造函数<br>'; } function __destruct(){ echo '调用了析构函数<br>'; } function __wakeup(){ echo '调用了苏醒函数<br>'; } } echo '创建对象a<br>'; $a = new ABC; echo '序列化<br>'; $a_ser=serialize($a); echo '反序列化<br>'; $a_unser = unserialize($a_ser); echo '对象快要死了!'; ?>
运行结果:
创建对象a 调用了构造函数 序列化 反序列化 调用了苏醒函数 对象快要死了!调用了析构函数 调用了析构函数
代码分析:
参考链接: https://www.cnblogs.com/20175211lyz/p/11403397.html class 这个关键字 一看就能看出来 这是一个类 定义三个函数 每个函数 都有一个魔术方法 __construct() 函数 当你创建对象的时候会自动触发此魔术方法 __destruct() 函数 反序列化结束后触发这个方法 简单理解代码都执行后自动触发 __wakeup() 函数 若反序列化函数unserialize存在 优先调用此方法 代码从第一行运行 因为创建了一个类 类中有函数 所以前面三个函数只有在调用的时候 才会触发 然后执行第一个echo 打印出 "创建对象" 此时 创建了对象 会自动触发__construct方法 打印出 "调用了构造函数" 继续向下执行代码 打印 "序列化" 序列化函数没有执行 跳过打印 " 反序列化" 反序列化函数执行后 优先执行__wakeup魔术方法 打印 "调用了苏醒函数" 此时 反序列化进程结束了 打印 "对象快死了" 并触发__destruct 方法 打印 "调用了析构函数" 最后整段代码结束 再次触发析构函数 完
网上公开的靶场讲解 (感谢这位大佬)
http://111.67.196.76:1088/unserialize/01/index.php
提示 /index.php?re=hello
所以url传参方式re = 序列化字符
解题思路
观察代码 利用文件读写函数 把hello.php 内容更改 获取反序列化 定义了类 类中__destruct魔术方法 unserialize函数 代码从上到下分析 类中定义tes变量 函数中使用文件操作 对hello.php文件进行写入 fputs函数 打开这个文件 把test变量的值写入此文件 然后关闭文件 创建一个类 使用re参数接收数据 并使用stripslashes函数 去掉反斜杠 然后调用反序列化函数
得知流程后 把代码复制到phpstom里 然后精简代码 进行序列化
<?php class a { // 有类序列化 var $test = 'hello'; // 关键变量 是将此变量值写入文件里 } $class = new a(); // 创建对象 echo(serialize($class)); // 获取数据 ?> O:1:"a":1:{s:4:"test";s:5:"hello";}
此时 内容已成功显示出来 。
所以说 学习反序列化 还是要求有一定的代码基础
IT界 以后不会编程,真的很难存活。