[2020 新春红包题]1

[2020 新春红包题]1

考点

  • PHP代码审计

  • 文件上传目录进行拼接,可以使用/../截断

  • 使用substr或其他类似函数限制文件后缀,可以使用/.绕过

  • 在shell中,反引号的优先级是高于引号的,所以会先执行反引号中的内容,然后再将执行结果拼接成一个新的命令

wp

给了源码,和[EIS 2019]EzPOP类似,反序列化由__destruct 入手,从A类开始

class A {
    protected $store;
    protected $key;
    protected $expire;

    public function __construct($store, $key = 'flysystem', $expire = null) {
        $this->key = $key;
        $this->store = $store;
        $this->expire = $expire;
    }
    public function cleanContents(array $contents) {
        $cachedProperties = array_flip([
            'path', 'dirname', 'basename', 'extension', 'filename',
            'size', 'mimetype', 'visibility', 'timestamp', 'type',
        ]);    //array(10) { ["path"]=> int(0) ["dirname"]=> int(1) ["basename"]=> int(2) ["extension"]=> int(3) ["filename"]=> int(4) ["size"]=> int(5) ["mimetype"]=> int(6) ["visibility"]=> int(7) ["timestamp"]=> int(8) ["type"]=> int(9) } 

        // 2.如果是二维数组,进入if,否则直接返回
        foreach ($contents as $path => $object) {
            if (is_array($object)) {
                $contents[$path] = array_intersect_key($object, $cachedProperties);
            }
        }
        return $contents;
    }
    
    public function getForStorage() {
        // cache是个数组,cleaned也是个数组
        $cleaned = $this->cleanContents($this->cache);
        // 3. 把数组转成json字符串返回
        return json_encode([$cleaned, $this->complete]);
    }

    public function save() {
        $contents = $this->getForStorage();
        // 4.store是B类
        $this->store->set($this->key, $contents, $this->expire);
    }

    public function __destruct() {
        if (!$this->autosave) {    // 1.autosave=false
            $this->save();
        }
    }
}

A类的大概逻辑写到了上面的注释中,再看B类

本题与[EIS 2019]EzPOP的区别是,A类中的key后四位不能是.php ,并且用uniqid()伪随机函数重命名文件。

第一种做法

由于文件名是直接使用. 拼接的,这样就会造成目录穿越,并且可以在文件末尾可以使用/. 绕过后缀限制。

payload

第二种做法

在创建文件后,它执行了$data = $this->serialize($data) 这段代码,而serialize函数可以使用system,$data 可以使用包含```` 的字符串

如果让A的cache为['cat /flag > ./flag.php'] ,B的options['serialize']为system ,那么最后执行的语句就是

在shell中,反引号的优先级是高于引号的,所以会先执行反引号中的内容,然后再将执行结果拼接成一个新的命令

第三种做法

与第一种大同小异

先写一个 .user.ini,然后写一个 .jpg 里面带马,使其追加到其他 php 后面作为 php 执行即可

包含shell的图片

然后上传.user.ini

小结

最后更新于