没事发个Discuz! X系列全版本后台sql注入漏洞

  • A+
所属分类:安全文章
没事发个Discuz! X系列全版本后台sql注入漏洞

没事发个Discuz! X系列全版本后台sql注入漏洞

铸剑学院 是首个依托于一线实战人员社区生态使“列装靶场+职业生态”形成良性互补的人才培训体系。它不但可以帮助用户循序渐进的掌握各种网络实战攻防技术,同时也是一个可以完全真实模拟生产环境,通过真实打击内网靶机,破除眼高手低的魔咒,实现真正的技术提升。

悬剑-单兵武器库,是一款全面的红队/网侦/取证的操作系统,他不但集成了很多业内稍纵即逝的神兵利器,还将运行环境、变量系统全部一一搞定,节省使用者大量的调试时间,上手即可用,全面无遗漏;配合铸剑靶场架设仿真环境,悬剑实操击打靶标,可以无缝的将靶场的技术储备能力转换到实战中来。


原创作者: [email protected]无糖信息阿斯巴甜攻防实验室@secquan仗剑联盟


没事发个Discuz! X系列全版本后台sql注入漏洞


Discuz! X系列全版本后台sql注入漏洞,注意是后台注入。

前序

已经提交给TSRC了,快过年了 就发出来吧,大家还是要多分享多交流。。。

漏洞版本

Discuz! X系列全版本 截止到 Discuz! X3.4 R20191201 UTF-8

漏洞详情

挖过discuz 漏洞的都知道 它会对大部分传参进来的值进行过滤和校验 ,所以当时找了一个二次注入的点

uc_servermodelbase.php 37行

<?php

/*
[UCenter] (C)2001-2099 Comsenz Inc.
This is NOT a freeware, use is subject to license terms

$Id: base.php 1167 2014-11-03 03:06:21Z hypowang $
*/

!defined('IN_UC') && exit('Access Denied');

class base {

var $sid;
var $time;
var $onlineip;
var $db;
var $view;
var $user = array();
var $settings = array();
var $cache = array();
var $app = array();
var $lang = array();
var $input = array();

function __construct() {
$this->base();
}

function base() {
$this->init_var();
$this->init_db();
$this->init_cache();
$this->init_app();
$this->init_user();
$this->init_template();
$this->init_note(); //跟进
$this->init_mail();
}



uc_servermodelbase.php 198行 开始

function init_note() {
if($this->note_exists()) { //跟进
$this->load('note');
$_ENV['note']->send();
}
}

function note_exists() {
$noteexists = $this->db->result_first("SELECT value FROM ".UC_DBTABLEPRE."vars WHERE name='noteexists".UC_APPID."'"); //从配置文件取值UC_APPID
return FALSE;
} else {
return TRUE;
}
}

查找UC_APPID

sourceadmincpadmincp_setting.php 2523行

$settingnew = $_GET['settingnew']; //传入

if($operation == 'credits') {
$extcredits_exists = 0;
foreach($settingnew['extcredits'] as $val) {
if(isset($val['available']) && $val['available'] == 1) {
$extcredits_exists = 1;
break;
}
}
if(!$extcredits_exists) {
cpmsg('setting_extcredits_must_available');
}
if($settingnew['report_reward']) {
$settingnew['report_reward']['min'] = intval($settingnew['report_reward']['min']);
$settingnew['report_reward']['max'] = intval($settingnew['report_reward']['max']);
if($settingnew['report_reward']['min'] > $settingnew['report_reward']['max']) {
unset($settingnew['report_reward']);
}
if($settingnew['report_reward']['min'] == $settingnew['report_reward']['max']) {
$settingnew['report_reward'] = array('min' => '', 'max' => '');
}
$settingnew['report_reward'] = serialize($settingnew['report_reward']);
}
$settingnew['creditspolicy'] = @dunserialize($setting['creditspolicy']);
$settingnew['creditspolicy']['lowerlimit'] = array();
foreach($settingnew['lowerlimit'] as $key => $value) {
if($settingnew['extcredits'][$key]['available']) {
$settingnew['creditspolicy']['lowerlimit'][$key] = (float)$value;
}
}
unset($settingnew['lowerlimit']);
}
if($operation == 'uc' && is_writeable('./config/config_ucenter.php') && $isfounder) {
require_once './config/config_ucenter.php';

$ucdbpassnew = $settingnew['uc']['dbpass'] == '********' ? addslashes(UC_DBPW) : addslashes($settingnew['uc']['dbpass']);
$settingnew['uc']['key'] = addslashes($settingnew['uc']['key'] == '********' ? addslashes(UC_KEY) : $settingnew['uc']['key']);

if(function_exists("mysql_connect") && ini_get("mysql.allow_local_infile")=="1" && constant("UC_DBHOST") != $settingnew['uc']['dbhost']){
cpmsg('uc_config_load_data_local_infile_error', '', 'error');
}

if($settingnew['uc']['connect']) {
$uc_dblink = function_exists("mysql_connect") ? @mysql_connect($settingnew['uc']['dbhost'], $settingnew['uc']['dbuser'], $ucdbpassnew, 1) : new mysqli($settingnew['uc']['dbhost'], $settingnew['uc']['dbuser'], $ucdbpassnew);
if(!$uc_dblink) {
cpmsg('uc_database_connect_error', '', 'error');
} else {
if(function_exists("mysql_connect")) {
mysql_close($uc_dblink);
} else {
$uc_dblink->close();
}
}
}

$fp = fopen('./config/config_ucenter.php', 'r');
$configfile = fread($fp, filesize('./config/config_ucenter.php'));
$configfile = trim($configfile);
$configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;
fclose($fp);

$connect = '';
$settingnew['uc'] = daddslashes($settingnew['uc']);
if($settingnew['uc']['connect']) {
$connect = 'mysql';
$samelink = ($dbhost == $settingnew['uc']['dbhost'] && $dbuser == $settingnew['uc']['dbuser'] && $dbpw == $ucdbpassnew);
$samecharset = !($dbcharset == 'gbk' && UC_DBCHARSET == 'latin1' || $dbcharset == 'latin1' && UC_DBCHARSET == 'gbk');
$configfile = str_replace("define('UC_DBHOST', '".addslashes(UC_DBHOST)."')", "define('UC_DBHOST', '".$settingnew['uc']['dbhost']."')", $configfile);
$configfile = str_replace("define('UC_DBUSER', '".addslashes(UC_DBUSER)."')", "define('UC_DBUSER', '".$settingnew['uc']['dbuser']."')", $configfile);
$configfile = str_replace("define('UC_DBPW', '".addslashes(UC_DBPW)."')", "define('UC_DBPW', '".$ucdbpassnew."')", $configfile);
if(!preg_match('/^[wd_]+$/', $settingnew['uc']['dbtablepre']) || !preg_match('/^[wd_]+$/', $settingnew['uc']['dbname'])) {
cpmsg('uc_config_write_error', '', 'error');
}
$configfile = str_replace("define('UC_DBNAME', '".addslashes(UC_DBNAME)."')", "define('UC_DBNAME', '".$settingnew['uc']['dbname']."')", $configfile);
$configfile = str_replace("define('UC_DBTABLEPRE', '".addslashes(UC_DBTABLEPRE)."')", "define('UC_DBTABLEPRE', '`".$settingnew['uc']['dbname'].'`.'.$settingnew['uc']['dbtablepre']."')", $configfile);
}
$configfile = str_replace("define('UC_CONNECT', '".addslashes(UC_CONNECT)."')", "define('UC_CONNECT', '".$connect."')", $configfile);
$configfile = str_replace("define('UC_KEY', '".addslashes(UC_KEY)."')", "define('UC_KEY', '".$settingnew['uc']['key']."')", $configfile);
$configfile = str_replace("define('UC_API', '".addslashes(UC_API)."')", "define('UC_API', '".$settingnew['uc']['api']."')", $configfile);
$configfile = str_replace("define('UC_IP', '".addslashes(UC_IP)."')", "define('UC_IP', '".$settingnew['uc']['ip']."')", $configfile);
$configfile = str_replace("define('UC_APPID', '".addslashes(UC_APPID)."')", "define('UC_APPID', '".$settingnew['uc']['appid']."')", $configfile);

$fp = fopen('./config/config_ucenter.php', 'w');
if(!($fp = @fopen('./config/config_ucenter.php', 'w'))) {
cpmsg('uc_config_write_error', '', 'error');
}
@fwrite($fp, trim($configfile)); // 写入到config_ucenter.php 可控UC_APPID 的值 通过上面代码可以看出来只简单的addslashes了一下
@fclose($fp);
}

isset($settingnew['regname']) && empty($settingnew['regname']) && $settingnew['regname'] = 'register';
isset($settingnew['reglinkname']) && empty($settingnew['reglinkname']) && $settingnew['reglinkname'] = cplang('reglinkname_default');
$nohtmlarray = array('bbname', 'regname', 'reglinkname', 'icp', 'sitemessage', 'site_qq');
foreach($nohtmlarray as $k) {
if(isset($settingnew[$k])) {
$settingnew[$k] = dhtmlspecialchars($settingnew[$k]);
}
}

if(isset($settingnew['statcode'])) {
$settingnew['statcode'] = preg_replace('/languages*=[s|'|"]*php/is', '_', $settingnew['statcode']);
$settingnew['statcode'] = str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $settingnew['statcode']);
}

转义一次的字符串被写人文件中,在PHP解析时就是没有转义过的原始内容 造成了二次注入的产生

<?php
define('UC_APPID', 'sadsadsadasd'');
printf(UC_APPID);

没事发个Discuz! X系列全版本后台sql注入漏洞

漏洞验证

没事发个Discuz! X系列全版本后台sql注入漏洞

burp登场

没事发个Discuz! X系列全版本后台sql注入漏洞

直接构造语句

1' into outfile 'c:\wamp64\tmp\1.txt'  -- a

没事发个Discuz! X系列全版本后台sql注入漏洞

没事发个Discuz! X系列全版本后台sql注入漏洞

构造报错注入

没事发个Discuz! X系列全版本后台sql注入漏洞


然后EXP就呼之欲出了~

因为众所周知的原因嘛,EXP就靠各位大手子自行安排!~



 警告:

本文非作者允许禁止转载,违者追究到底!

本文非作者允许禁止转载违者追究到底!

本文非作者允许禁止转载违者追究到底!


最后祝贺我老铁无双老板的铸剑学院CISP-PTE专班顺利举办~(主要想要战袍+1)



没事发个Discuz! X系列全版本后台sql注入漏洞


欢迎关注 圈子社区官方公众号,

不花钱,不求人、获得最新职业红队资源!


公益,鲜活,专业


没事发个Discuz! X系列全版本后台sql注入漏洞
没事发个Discuz! X系列全版本后台sql注入漏洞
没事发个Discuz! X系列全版本后台sql注入漏洞

关于圈子社区:

我们是一个非盈利,封闭的白帽子技术交流社区。目前成员2000+,拥有业内首个自主研发的红蓝实战靶场(公安部已列装),体系化学习和燃爆的交流气氛助你成为真正的大佬,社区专注实战,崇尚技术,如果你也是实战派,请关注我们。

社区地址:(请使用https访问)

https://www.secquan.org


没事发个Discuz! X系列全版本后台sql注入漏洞
没事发个Discuz! X系列全版本后台sql注入漏洞



本文始发于微信公众号(Secquan圈子社区):没事发个Discuz! X系列全版本后台sql注入漏洞

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: