[网鼎杯2020 青龙组]AreUSerialz

源代码:

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

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

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->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!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    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;
    }

    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方式传入str,is_valid函数会校验传入的 反序列化后的str值的ascii在32和125之间。

并触发析构方法_destruct()

如果传入的op值 强类型比较 等于2

则变为1

否则将content边为空

并进入process函数:

在process函数中,

如果op值等于1 进入write函数

如果op值  “弱类型比较”  等于2 ,将read函数值赋给res,并通过output函数显示出来:

查看write函数:

Read函数:

可知

  • 我们需要用read函数,读取flag.php文件
  • 进入flag则需要op的值等于2

则需要:

_destruct中的 op===”2”  结果为false

Process中的 op == “2” true

只需要将 使 op = 2

强类型检测类型不同 返回false

弱类型 会转化为相同类型再对比  即返回true

构造 pyload:

在本地序列化:

需注意,在源码中,三个变量为p$op,$filename,$content三个变量权限都是protected,而protected权限的变量在序列化的时会有%00*%00字符,%00字符的ASCII码为0,就无法通过上面的is_valid函数校验。

在序列化时候将protected改为public即可解决:

通过str传上去

在源码中即可看到

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注