如何渗透Discuz论坛(一)


Jun 19 2016

如何渗透Discuz论坛(一)

首页 » 原创作品 » 如何渗透Discuz论坛(一)   

如何渗透Discuz论坛(一)

作者:mOon    
博客:www.moonsec.com

0x01:叙述:

这几篇文章主要的分享给那些经常渗透Discuz 或者对 Discuz论坛无从下手的初学者,可能帮助或者提高你对Discuz论坛的安全认知,从而找到突破的方法,这几篇都是作者真实渗透的案例,如有雷同纯属巧合,毕竟渗透手法基本相同嘛。

u=3158184602,2280209766&fm=21&gp=0.jpg

 

 



0x02:Discuz简介



        u=2475099916,3960809165&fm=21&gp=0_看图王.jpg

Crossday Discuz! Board(以下简称 Discuz!,中国国家版权局著作权登记号 2006SR11895)是康盛创想(北京)科技有限公司(英文简称Comsenz)推出的一套通用的社区论坛软件系统,用户可以在不需要任何编程的基础上,通过简单的设置和安装,在互联网上搭建起具备完善功能、很强负载能力和可高度定制的论坛服务。Discuz! 的基础架构采用世界上最流行的 web 编程组合 PHP+MySQL实现,是一个经过完善设计,适用于各种服务器环境的高效论坛系统解决方案。
作为国内最大的社区软件及服务提供商,Comsenz旗下的 Discuz! 开发组具有丰富的 web 应用程序设计经验,尤其在论坛产品及相关领域,经过长期创新性开发,掌握了一整套从算法,数据结构到产品安全性方面的领先技术。使得 Discuz! 无论在稳定性,负载能力,安全保障等方面都居于国内外同类产品领先地位。

暗月论坛也是Discuz论坛 使用多年了,安全性 感觉还行,最近的几个漏洞,都是要配合第三方 才能获取权限,所以关于Discuz论坛,一般情况下是很难渗透,除某些大牛手里有大杀器除外。不过这类大牛一般都看不起我们这些站 因为 没有必要下手。一不小心被我获取了,想想也有点小激动。QQ图片20160618122328.gif

 

 

0x03 常见问题:

  • Discuz怎么破解
  • Discuz问题破解
  • Discuz删帖
  • Discuz权限绕过
  • Discuz后台获webshell

   以上这种这类问题,天天有人私聊,或者在群里提问。提问是对,但是这种问题不是一两句话,说得明白的。QQ图片20160618121538.jpg

 

0x04 案例一:

 u=1639207181,4175380361&fm=116&gp=0.jpg

看上某站一个插件,但是在插件中心又看不见。怎么办,我们可以在谷歌搜索这类插件。
inurlplugin.php?id=这里是插件名 例如我想要微信机机器人这个插件 wuxin_qqrobo

2.png

 

 

1.png

 

目标确认后,新手如何渗透这样的论坛。记得年前有个基佬写了一款工具名为《Dzscan》针对Discuz论坛安全检测的工具。

 Dzscan项目设计的初衷,一方面是向wpscan,jmscan的等国外优秀作品的致敬,另一方面是更符合国情的量身定做。针对国内知名bbs建站系统discuz,所精心打造的一款漏洞扫描框架.
此处为discuz第三方漏洞收集和发布平台,当前的数十个漏洞都由Dzscan团队成员所发掘,为Dzscan能走更远而努力。
国内的大环境所决定,分享不易,漏洞分享更不易。未来,我们希望更多的小伙伴参与到对discuz的代码审计中去。作为国内极为优秀的一款开源cms,多读读其代码也是有益的。
为防止恶意利用,现今只公开低位和中危的漏洞,高危的开放与否留待后期再做决定。

 

如此富有文学和深度的介绍,相信这个工具能给我们带来帮助。不过高危漏洞的不开放,这样真的好吗。作者选择性搞基 ,这点我也无可奈何QQ图片20160618141055.jpg
 
这个工具更不更新插件都没关系了,因为插件的exp漏洞 高危的漏洞,团队还真没放出来,而且最近新的漏洞,模块也没更新,估计网站也是快倒闭的,还没把网站内网保存的的同学,快点保存吧。
装个python scan go
3.png
 

先对目标干一炮:

 4.png

好像记得 utility 曾经有个漏洞,可以直接GETSHELL的。不急 我们先看下源码有没有加载exp模块的功能。

def fetch_sensitive(self):
        # X3 Deafult password 188281MWWxjk
        # https://www.bugscan.net/#!/n/449
        robots_path = '%s/%s' % (self.url, '/source/plugin/tools/tools.php')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path       
        # X3.1 Remote code execute
        # https://www.sebug.net/vuldb/ssvid-61217
        robots_path = '%s/%s' % (self.url, '/utility/convert/index.php?a=config&source=d7.2_x2.0')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path   
        
        # 7.2 faq.php SQL
        # https://www.bugscan.net/#!/n/118
        robots_path = '%s/%s' % (self.url, '/faq.php')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # 7.2 manyou SQL
        # http://www.venustech.com.cn/NewsInfo/124/6791.Html
        robots_path = '%s/%s' % (self.url, '/manyou/userapp.php')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # 7.2 admincp.php XSS 
        # https://www.bugscan.net/#!/n/141
        robots_path = '%s/%s' % (self.url, '/manyou/admincp.php?my_suffix=%0A%0DTOBY57')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # 6.x SQL 
        # http://www.wooyun.org/bugs/wooyun-2014-080359
        robots_path = '%s/%s' % (self.url, '/my.php')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # deafult admin login page
        robots_path = '%s/%s' % (self.url, '/admin.php')
        req = requests.get(robots_path, headers=HEADERS, allow_redirects=False)
        self.reqs += 1
        if req.status_code == 200 and 'Comsenz' in req.content:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # deafult uc_server login page
        robots_path = '%s/%s' % (self.url, '/uc_server/admin.php')
        req = requests.get(robots_path, headers=HEADERS, allow_redirects=False)
        self.reqs += 1
        if req.status_code == 200 and 'UCenter' in req.content:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path

        # develop.php
        robots_path = '%s/%s' % (self.url, '/develop.php')
        req = requests.get(robots_path, headers=HEADERS)
        self.reqs += 1
        if req.status_code == 200:
            print '[!] The Discuz! \'%s\' file exists.\n' % robots_path  


 

 

只是单纯的扫描确认文件存在否,没有加载exp模块,拿出内部EXP工具 GETSHELL

图片3_看图王.png

菜刀连接:
 
效果演示二.png
 
 
实在意料之外这么简单就搞定目标了。QQ图片20160618142113.jpg
 
0x05:漏洞分析
 
Utility/convert/index.php
<?php

/**
* DiscuzX Convert
*
* $Id: index.php 10469 2010-05-11 09:12:14Z monkey $
*/

require './include/common.inc.php';

$action = getgpc('a');
$action = empty($action) ? getgpc('action') : $action;
$source = getgpc('source') ? getgpc('source') : getgpc('s');
$step = getgpc('step');
$start = getgpc('start');

$setting = array();
if($source) {
        if(!$setting = loadsetting($source)) {
                showmessage('load_setting_error');
        }
}

$action = empty($action) || empty($source) ? 'source' : $action;
showheader($action, $setting);

if($action == 'source') {
        require DISCUZ_ROOT.'./include/do_source.inc.php';
} elseif($action == 'config' || CONFIG_EMPTY) {
        require DISCUZ_ROOT.'./include/do_config.inc.php';
} elseif($action == 'setting') {
        require DISCUZ_ROOT.'./include/do_setting.inc.php';
} elseif($action == 'select') {
        require DISCUZ_ROOT.'./include/do_select.inc.php';
} elseif($action == 'convert') {
        require DISCUZ_ROOT.'./include/do_convert.inc.php';
} elseif($action == 'finish') {
        require DISCUZ_ROOT.'./include/do_finish.inc.php';
} else {
        showmessage('非法请求');
}

showfooter();
?>
require DISCUZ_ROOT.'./include/do_config.inc.php';
?php

/**
* DiscuzX Convert
*
* $Id: do_config.inc.php 10469 2010-05-11 09:12:14Z monkey $
*/

if(!defined('DISCUZ_ROOT')) {
        exit('Access error');
}

$configfile = DISCUZ_ROOT.'./data/config.inc.php';
$configfile_default = DISCUZ_ROOT.'./data/config.default.php';

@touch($configfile);//创建文件
if(!is_writable($configfile)) {//文件是否可写
        showmessage('config_write_error');
}

$config_default = loadconfig('config.default.php');//载入默认配置文件
$error = array();
if(submitcheck()) {//检测是否提交
        $newconfig = getgpc('newconfig');
        if(is_array($newconfig)) {//是否为数组
                $checkarray = $setting['config']['ucenter'] ? array('source', 'target', 'ucenter') : array('source', 'target');
                foreach ($checkarray as $key) {
                        if(!empty($newconfig[$key]['dbhost'])) {
                                $check = mysql_connect_test($newconfig[$key], $key);
                                if($check < 0) {
                                        $error[$key] = lang('mysql_connect_error_'.abs($check));
                                }
                        } else {
                                $error[$key] = lang('mysql_config_error');
                        }
                }
                save_config_file($configfile, $newconfig, $config_default);
                if(empty($error)) {
                        $db_target = new db_mysql($newconfig['target']);
                        $db_target->connect();
                        delete_process('all');
                        showmessage('config_success', 'index.php?a=select&source='.$source);
                }
        }
}

showtips('如果无法显示设置项目,请删除文件 data/config.inc.php');
$config = loadconfig('config.inc.php');
if(empty($config)) {
        $config = $config_default;
}
show_form_header();
show_config_input('source', $config['source'], $error['source']);
show_config_input('target', $config['target'], $error['target']);
if($setting['config']['ucenter']) {
        show_config_input('ucenter', $config['ucenter'], $error['ucenter']);
}
show_form_footer('submit', 'config_save');

?>
跟踪save_config_file 函数
function lang($name, $vars = array()) {
        static $language;
        if($language === null) {
                @include DISCUZ_ROOT.'./language/lang.php';
                if(empty($language)) {
                        $language = array();
                }
        }
        $ret = isset($language[$name]) ? $language[$name] : $name;
        if(!empty($vars)) {
                foreach ($vars as $key => $value) {
                        $ret = str_replace('{'.$key.'}', $value);
                }
        }
        return $ret;
}

function show_hidden_field($name, $value) {
        echo '<input type="hidden" name="'.$name.'" value="'.$value.'">'."\n";
}

function show_form_header($method = 'post') {
        echo <<<EOT
<form method="$method" action="index.php">
<input type="hidden" name="a" value="$GLOBALS[action]">
<input type="hidden" name="source" value="$GLOBALS[source]">
<input type="hidden" name="submit" value="yes">
EOT;
}

function show_form_footer($submitname = '', $submitvalue = 'submit') {
        if($submitname != '') {
                $submitvalue = lang($submitvalue);
                echo <<<EOT
<table class="button">
        <tr><td><input type="submit" value="$submitvalue" name="$submitname"></td></tr>
</table>
EOT;
        }
        echo '</form>';
}

function show_config_input($type, $config, $error = array()) {
        $title = lang('config_type_'.$type);
        show_table_header();
        show_table_row(array(array('colspan="3"', $title)), 'header title');
        if($type == 'target') {
                show_table_row(array(array('colspan="3"', '<font color="red">'.lang('config_type_target_comment').'</font>')), 'bg2');
        }
        foreach ($config as $key => $value) {
                $addmsg = $error && $key == 'dbhost' ? lang($error) : '';
                $tip = $key == 'pconnect' ? lang('tips_pconnect') : '';
                show_table_row(        array(
                array('width="150"', lang('config_'.$key)),
                array('class="bg2"', '<input type="text" size="40" name="newconfig['.$type.']['.$key.']" value="'.htmlspecialchars($value).'">'),
                array('class="bg2"', '<font color="red">'.$tip.'</font><font color="red">'.$addmsg.'</font>')
                ), 'bg1'
                );
        }

        show_table_footer();
        echo '<br>';
}

function getvars($data, $type = 'VAR') {
        $evaluate = '';
        foreach($data as $key => $val) {
                if(!preg_match("/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/", $key)) {
                        continue;
                }
                if(is_array($val)) {
                        $evaluate .= buildarray($val, 0, "\${$key}")."\r\n";
                } else {
                        $val = addcslashes($val, '\'\\');
                        $evaluate .= $type == 'VAR' ? "\$key = '$val';\n" : "define('".strtoupper($key)."', '$val');\n";
                }
        }
        return $evaluate;
}

function buildarray($array, $level = 0, $pre = '$_config') {
        static $ks;
        if($level == 0) {
                $ks = array();
                $return = '';
        }

        foreach ($array as $key => $val) {

                if($level == 0) {
                        $newline = str_pad('  CONFIG '.strtoupper($key).'  ', 50, '-', STR_PAD_BOTH);
                        $return .= "\r\n// $newline //\r\n";
                }

                $ks[$level] = $ks[$level - 1]."['$key']";
                if(is_array($val)) {
                        $ks[$level] = $ks[$level - 1]."['$key']";
                        $return .= buildarray($val, $level + 1, $pre);
                } else {
                        $val = !is_array($val) && (!preg_match("/^\-?[1-9]\d*$/", $val) || strlen($val) > 12) ? '\''.addcslashes($val, '\'\\').'\'' : $val;
                        $return .= $pre.$ks[$level - 1]."['$key']"." = $val;\r\n";
                }
        }
        return $return;
}

function save_config_file($filename, $config, $default) {
        $config = setdefault($config, $default);

        $date = gmdate("Y-m-d H:i:s", time() + 3600 * 8);
        $year = date('Y');
        $content = <<<EOT
<?php


\$_config = array();

EOT;
        $content .= getvars(array('_config' => $config));
        $content .= "\r\n// ".str_pad('  THE END  ', 50, '-', STR_PAD_BOTH)." //\r\n\r\n?>";
        file_put_contents($filename, $content);
}

function setdefault($var, $default) {
        foreach ($default as $k => $v) {
                if(!isset($var[$k])) {
                        $var[$k] = $default[$k];
                } elseif(is_array($v)) {
                        $var[$k] = setdefault($var[$k], $default[$k]);
                }
        }
        return $var;
}
 简单点来说,创建文件config.inc.php  然去加载 config.default.php 替换内容没有过滤 写入 config.inc.php

0x06:扩展:

最近暗月有时间会写下关于Discuz渗透方面的文章,这是开头篇,欢迎长期关注暗月论坛微信号 (moonsec)和本论坛。

dzscan team:http://dzscan.org/

moon_Discuz_utility 下载:moon_Discuz_utility.zip

 

 

如果您喜欢本博客,欢迎点击图片定订阅到邮箱填写您的邮件地址,订阅我们的精彩内容:

正文部分到此结束

文章标签: Discuz漏洞 渗透Discuz Discuz破解

版权声明:若无特殊注明,本文皆为( mOon )原创,转载请保留文章出处。

也许喜欢: «Yii防注入攻击笔记 - imxiu | burpsuite 1.7.03最新破解版»

你肿么看?

你还可以输入 250/250 个字

 微笑 大笑 拽 大哭 亲亲 流汗 喷血 奸笑 囧 不爽 晕 示爱 害羞 吃惊 惊叹 爱你 吓死了 呵呵

评论信息框

已有6条评论

匿名

2017-11-16 15:23 4楼
骚包....的确骚...

匿名

2016-06-23 19:21 地板
弱弱的问就第一个Python脚本怎么用

mOon

2016-06-29 10:21
@匿名:装个库

匿名

2016-06-23 14:10 板凳

匿名

2016-06-21 22:44 沙发
dzscan怎么安装不成功啊........求教

mOon

2016-06-29 10:33
@匿名:装python