DiscuzML 3.x 代码注入

前言

漏洞刚出来时候发现分析文章很少,只能自己审计审计。根据poc,首先要排除是否是文件名导致的代码注入(可能就我在纠结这个吧,太菜了估计)。
带这个疑问了下群里@xq17师傅,在自己进行如下验证。
通过修改缓存内容判断是读内容导致代码注入,还有就是查看文件包含点,是include_once 如果有可执行代码会报出error直接结束程序。

复现环境

php5.6
deepin
版本Discuz!ML 3.4

漏洞验证

根据poc,将cookie中language字段拼接'.phpinfo().'可实现代码注入

漏洞触发原因

未过滤cookie输入

漏洞分析

通过debug报错找到文件包含处在文件/upload/source/module/portal/portal_index.php第32行

include_once template('diy:portal/index');

跟进该函数查看返回值为"DISCUZ_ROOT.$cachefile;",溯源$cachefile
其中DISCUZ_LANG值为cookie中字段language值可控,导致$cachfile文件名可控

$this->var['oldlanguage'] = $lng; // Store Old Language Value for compare

// define DISCUZ_LANG
define('DISCUZ_LANG', $lng);

$cachefile = './data/template/'.DISCUZ_LANG.'_'.(defined('STYLEID') ? STYLEID.'_' : '_').$templateid.'_'.str_replace('/', '_', $file).'.tpl.php';

跟进模板操作函数checktplrefresh,跟进parse_template模板解析函数。文件/upload/source/class/class_template.php第84行将$headeradd拼接进模板中,往回看该文件70-77行。
headeradd字符串拼接为|| checktplrefresh('$tplfile', '$fname', ".time().", '$templateid', '$cachefile', '$tpldir', '$file')\n" ,其中$cachefile正好是可控,导致文件包含之后拼接的代码执行。

$headeradd = $headerexists ? "hookscriptoutput('$basefile');" : '';
if(!empty($this->subtemplates)) {
   $headeradd .= "\n0\n";
   foreach($this->subtemplates as $fname) {
      $headeradd .= "|| checktplrefresh('$tplfile', '$fname', ".time().", '$templateid', '$cachefile', '$tpldir', '$file')\n";
   }
   $headeradd .= ';';
}

可触发的代码的文件只有en’.phpinfo().’11_common_header_portal_index.tpl.php


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!