Hisiphp代码审计后台getshell

漏洞CMS

版本:V 2.0.11 https://gitee.com/hisi/hisiph

漏洞描述:

在后台上传插件处,通过上传构造的恶意zip 压缩包文件,从而获取到服务器的权限

漏洞路径

漏洞地址:/admin.php/system/plugins/import.html
漏洞代码路径:hisiphp/application/system/admin/Plugins.php

public function import()
{
    
    
        if ($this->request->isPost()) {
    
    
            $file = $this->request->file('file');
            if (empty($file)) {
    
    
                return $this->error('请上传模块安装包');
            }

            if (!$file->checkExt('zip')) {
    
    
                return $this->error('请上传 ZIP 格式的安装包');
            }

            $basePath = './upload/temp/file/';
            $file = $file->rule('md5')->move($basePath);
            $file = $basePath.$file->getSaveName();

            if (ROOT_DIR != '/') {
    
    // 针对子目录处理
                $file = realpath(str_replace(ROOT_DIR, '/', $file));
            }
            
            if (!file_exists($file)) {
    
    
                return $this->error('上传文件无效');
            }
            
            $decomPath = '.'.trim($file, '.zip');
            if (!is_dir($decomPath)) {
    
    
                Dir::create($decomPath, 0777);
            }
            
            // 解压安装包到$decomPath
            $archive = new PclZip();
            $archive->PclZip($file);
            if(!$archive->extract(PCLZIP_OPT_PATH, $decomPath, PCLZIP_OPT_REPLACE_NEWER)) {
    
    
                Dir::delDir($decomPath);
                @unlink($file);
                return $this->error('导入失败('.$archive->error_string.')');
            }

            // 获取插件名
            $files = Dir::getList($decomPath.'/upload/plugins/');

            if (!isset($files[0])) {
    
    
                Dir::delDir($decomPath);
                @unlink($file);
                return $this->error('导入失败,安装包不完整');
            }

            $appName = $files[0];

            // 防止重复导入插件
            if (is_dir(Env::get('root_path').'plugins/'.$appName)) {
    
    
                Dir::delDir($decomPath);
                @unlink($file);
                return $this->error('插件已存在');
            } else {
    
    
                Dir::create(Env::get('root_path').'plugins/'.$appName, 0777);
            }

            // 复制插件
            Dir::copyDir($decomPath.'/upload/plugins/'.$appName.'/', Env::get('root_path').'plugins/'.$appName);

            // 文件安全检查
            $safeCheck = Dir::safeCheck(Env::get('root_path').'plugins/'.$appName);
            if ($safeCheck) {
    
    
                foreach($safeCheck as $v) {
    
    
                    Log::warning('文件 '. $v['file'].' 含有危险函数:'.str_replace('(', '', implode(',', $v['function'])));
                }
            }

            // 复制静态资源
            Dir::copyDir($decomPath.'/upload/public/static/'.$appName, './static/plugins/'.$appName);

            // 删除临时目录和安装包
            Dir::delDir($decomPath);
            @unlink($file);

            $this->success($safeCheck ? '插件导入成功,部分文件可能存在安全风险,请查看系统日志' : '插件导入成功', url('index?status=0'));
        }

        $tabData = $this->tabData;
        $tabData['current'] = 'system/plugins/import';
        $this->assign('hisiTabData', $tabData);
        $this->assign('hisiTabType', 3);
        return $this->fetch();
    }

代码分析:
import 函数,首先判断isPost() 方法, 也就是POST 请求

public function isPost()
{
    
    
        return $this->method() == 'POST';
 }

然后判断file 文件名称是否为空和后缀名,只能为zip格式

    public function checkExt($ext)
{
    
    
        if (is_string($ext)) {
    
    
            $ext = explode(',', $ext);
        }

        $extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));

        if (!in_array($extension, $ext)) {
    
    
            $this->error = 'extensions to upload is not allowed';
            return false;
        }

        return true;
    }

$file = f i l e − > r u l e ( ′ m d 5 ′ ) − > m o v e ( file->rule('md5')->move( file>rule(md5)>move(basePath); 设置文件命名类型MD5
d e c o m P a t h 变量, t r i m ( ) 函数从字符串的两端删除空白字符和其他预定义字符 D i r : : c r e a t e ( decomPath 变量, trim() 函数从字符串的两端删除空白字符和其他预定义字符 Dir::create( decomPath变量,trim()函数从字符串的两端删除空白字符和其他预定义字符Dir::create(decomPath, 0777); 创建文件夹

$archive = new PclZip(); PclZip 类主要解压zip文件
在这里插入图片描述

漏洞利用复现

创建zip 压缩包
用来存放恶意文件
在这里插入图片描述
将构造的zip压缩包上传

在这里插入图片描述
在这里插入图片描述

上传并解压的php文件路径:
/upload/temp/file/8d/2e01fe4987eb614640e9f6f4a02f57/1.php
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_18193739/article/details/132765176
今日推荐