【攻防世界】unserialize3
进入场景,发现是一串不完整的代码

开始分析代码:
这个类包含一个公共属性 $flag 和一个魔术方法 __wakeup;
当一个对象被反序列化时,如果定义了 __wakeup 方法,该方法会被自动调用;
如果有人尝试反序列化一个 xctf 类型的对象,__wakeup 方法会被触发,并且脚本会立即退出并显示消息 'bad requests'。这通常被用作一种防止对象被反序列化的安全措施。
这道题目没有显示序列化的步骤,这提醒我们在传参时需要构造一个已经序列化的参数,而下面的code提醒我们传递的是这个参数。
本题涉及序列化与反序列化,我来简单介绍一下:
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
PHP序列化:将变量转换为可保存或传输的字符串的过程。
PHP序列化函数:serialize
参考实例:
<?php
class person{
public $name;
public $age;
function __construct($name, $age){
$this->name = $name;
$this->age = $age;
}
}
$p = new person("cx", 19);
echo serialize($p);
?>
输出结果:
O:6:"person":2:{s:4:"name";s:2:"cx";s:3:"age";i:19;}

使用以下代码可以产生序列化输出:
<?php class xctf{ public $flag = '111'; public function __wakeup(){ exit('bad requests'); } } $a = new xctf(); echo(serialize($a)); ?>
构造出的代码有以下输出:
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
需要注意的是,直接反序列化这个类的对象会导致脚本终止,因此无法继续执行任何操作。如果需要进一步的操作,应该避免触发 __wakeup 方法。

这里的漏洞就是:
PHP 在反序列化时,如果遇到属性数量的声明比实际多,它不会去调用
__wakeup 方法,因为它会尝试匹配更多的属性,直到遇到序列化的结束,这时它已经跳过了 __wakeup 方法的调用。例如,将序列化输出的对象个数改成比 1 大的数:
O:4:"xctf":3:{s:4:"flag";s:3:"111";}
这里,尽管
xctf 类实际上只有 1 个属性,但序列化字符串声明有 3 个属性。当这个序列化字符串被反序列化时,PHP 解释器会期望找到 3 个属性,但实际上只找到了 1 个,因此它不会调用 __wakeup 方法,从而绕过了 exit('bad requests') 的调用。- 所以,我们将序列化输出的对象个数改成比1大的数就行了
- 比如:
?code=O:4:"xctf":3:{s:4:"flag";s:3:"111";}flag就出来了:

flag:cyberpeace{b4fcacae71603a65095a1bed5009f51a}
刚做完攻防世界的unseping,做到这题感觉有点懵懵的——这两道为啥都是难度1啊?
这两题都与反序列化有关。想做另一道的也欢迎看我的那篇笔记作为参考:做题笔记-攻防世界-unseping


浙公网安备 33010602011771号