php版本7.1以上,对类属性检测不严格导致的反序列化问题

作者: const27 分类: All,PHP反序列化 发布时间: 2020-06-03 09:44

做题时遇到的小东西

php7.1+反序列化的对象可以直接以public属性的形式对原类中的protected形式的属性进行修改。
比如[网鼎杯 2020 青龙组]AreUSerialz一题。其难点在于你必须在反序列化payload中修改一个protected的属性才能拿到flag,但是有一个判断语句让你不能在反序列化payload出现%00字符。 所以此处我们在做payload的时候,把protected属性改成public属性再序列化也行。

    protected $op;
    protected $filename;
    protected $content;

    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!");
        }
    }
    
        private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

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

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

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

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

关键代码放这里。逻辑是从get参数获取数据并反序列化。然后我们通过反序列化payload操控op让它为2并且filename=flag.php。但是我们正常思路制造payload时因为op和filename是proteced属性,难免会有%00字符出现,但是它又让你不能出现%00这种ascii码小于32的字符。所以我们直接把op和filename当作public属性处理也可以直接过去
也就是说payload这样写

new  FileHandler{
    public $op=2;
    public $filename="flag.php"
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

Leave a Reply

Your email address will not be published. Required fields are marked *

标签云