【攻防世界】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

posted @ 2025-05-01 20:59  Antoniiiia  阅读(215)  评论(0)    收藏  举报