两道php反序列化题目分析

经典反序列化

<?php
error_reporting(1);
class Read {
    public $var;
    public function file_get($value)
    {
        $text = base64_encode(file_get_contents($value));
        return $text;
    }

/**
 * 尝试将$read()当作函数调用时会触发这个方法
 * @return [type] [description]
 */
    public function __invoke(){
        $content = $this->file_get($this->var);
        echo $content;
    }
}

class Show
{
    public $source;
    public $str;
    //此处可以触发__toString方法
    public function __construct($file='index.php')
    {
        $this->source = $file;
        echo $this->source.'Welcome'."<br>"; //此处有字符串拼接
    }

    /**
     * 假设这里可以触发__get方法,怎么触发__toString方法
     */
    public function __toString()
    {
        $this->str['str']->source;
    }

    public function _show()
    {
        if(preg_match('/gopher|http|ftp|https|dict|\.\.|flag|file/i',$this->source)) {
            die('hacker');
        } else {
            highlight_file($this->source); //其实这里也可以读文件但是好像没什么乱用
        }

    }

    public function __wakeup()
    {
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class Test
{
    /**
     * 将$p覆盖为read 就能触发Read类的__invoke方法,如何触发__get方法
     */
    public $p;
    public function __construct()
    {
        $this->p = array();
    }

    public function __get($key)
    {
        $function = $this->p;
        return $function();
    }
}

if(isset($_GET['hello']))
{
    unserialize($_GET['hello']);
}
else
{
    $show = new Show('index.php');
    $show->_show();
}

这道题还是在上大学的时候做的了,现在回过头来看,其中一个比较隐藏的点:

public function __construct($file='index.php')
{
    $this->source = $file;
    echo $this->source.'Welcome'."<br>"; //此处有字符串拼接
}

因为有字符串拼接,所以可以触发 __toString() 方法

另外一个惊喜则是deepseek