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

dzzoffice 任意文件下载漏洞分析的更多相关文章

  1. 【代码审计】XYHCMS V3.5任意文件下载漏洞分析

      0x00 环境准备 XYHCMS官网:http://www.xyhcms.com/ 网站源码版本:XYHCMS V3.5(2017-12-04 更新) 程序源码下载:http://www.xyhc ...

  2. 【代码审计】ThinkSNS_V4 任意文件下载漏洞分析

      0x00 环境准备 ThinkSNS官网:http://www.thinksns.com 网站源码版本:ThinkSNS V4  更新时间:2017-09-13 程序源码下载:http://www ...

  3. 【代码审计】EasySNS_V1.6 前台任意文件下载漏洞分析

      0x00 环境准备 EasySNS官网:http://www.imzaker.com/ 网站源码版本:EasySNS极简社区V1.60 程序源码下载:http://es.imzaker.com/i ...

  4. 【代码审计】CLTPHP_v5.5.3后台任意文件下载漏洞分析

      0x00 环境准备 CLTPHP官网:http://www.cltphp.com 网站源码版本:CLTPHP内容管理系统5.5.3版本 程序源码下载:https://gitee.com/chich ...

  5. 任意文件下载漏洞的接口URL构造分析与讨论

    文件下载接口的URL构造分析与讨论 某学院的文件下载接口 http://www.****.edu.cn/item/filedown.asp?id=76749&Ext=rar&fname ...

  6. 代码审计-(Ear Music).任意文件下载漏洞

    0x01 代码分析 后台地址:192.168.5.176/admin.php admin admin 安装后的界面 在后台发布了一首新歌后,前台点进去到一个“下载LRC歌词”功能点的时候发现是使用re ...

  7. PHP代码审计笔记--任意文件下载漏洞

    在文件下载操作中,文件名及路径由客户端传入的参数控制,并且未进行有效的过滤,导致用户可恶意下载任意文件.  0x01 客户端下载 常见于系统中存在文件(附件/文档等资源)下载的地方. 漏洞示例代码: ...

  8. 代码审计-phpcms9.6.2任意文件下载漏洞

    漏洞文件: phpcms\modules\content\down.php 1.在download函数中对文件的校验部分 首先 if(preg_match('/(php|phtml|php3|php4 ...

  9. WordPress插件会员简化1.58 -任意文件下载漏洞(附poc)

    今天我们将讨论在WordPress插件WordPress插件与重点会员简化v1.58作为这个剧本的创作时间不打补丁的扶贫开发实践.脆弱脚本如下: CVE-ID:cve-2017-1002008 当然, ...

随机推荐

  1. Kafka理论学习

    Kafka Consumer设计解析 http://www.jasongj.com/2015/08/09/KafkaColumn4/

  2. LwIP移植uCos+stm32f407

    LwIP同操作系统一起工作的时候模型如下: 1.TCP/IP协议栈和应用程序以分离的任务运行 2.应用同协议栈沟通是通过API函数调用(API函数调用事实上就是通过OS自带的进程间通信机制,由应用程序 ...

  3. android4.3 蓝牙BLE编程

    一.蓝牙4.0简介 蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low ...

  4. "makefile:5: *** missing separator. Stop."【转】

    本文转载自:http://blog.csdn.net/fireroll/article/details/8607903 写makefile时出现这个错误提示 是表示makefile中的命令前没有使用T ...

  5. Codeforces Round #401 (Div. 2) C Alyona and Spreadsheet —— 打表

    题目链接:http://codeforces.com/contest/777/problem/C C. Alyona and Spreadsheet time limit per test 1 sec ...

  6. ffmpeg视频格式转换中关键帧的设置

    在用ffmpeg转换视频到flv过程中,需要设置关键帧的间隔,以便在播放过程中实现精确定位.在网上查找了不少,最后发现这个指令有效: -g 1 -keyint_min 2 . http://blog. ...

  7. macbook清理磁盘空间

    前言:作为一名程序员,使用MacBook时间久了之后难免都会遇到“磁盘空间不足”的警告,这时就可以清理如下文件夹,一般就可以清理出几十个G的大小! 1.删除“~/资源库/Developer/Xcode ...

  8. Swing项目编译成exe,并且打包成安装文件(一)

    我们一般用java做Swing项目的时候一般都是只能在Myeclipse里面运行,那么怎么把我们的项目打包成exe可以直接双击运行呢? 初始工作:为了不让用户安装java环境,所以我们先新建一个文件夹 ...

  9. C++模板之隐式实例化、显示实例化、隐式调用、显示调用和模板特化详解

    模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程.对于函数模板而言,模板实例化之后,会生成一个真正的函数.而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始 ...

  10. Tyvj1052(树形DP)

    P1052 没有上司的舞会 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以 ...