这是一个比较有意思的东西,但是成功利用起来并不容易,呵呵。 首先看config_rglobals.php文件,摘的一段代码如下。这里作者本意是为了帮我们注册变量的,但是他却疏忽了我们不但能注册变量,还能覆盖一些变量。config_rglobals_magic.php也有同样的问题 ………………………………………………………………………… if(is_array($_GET)){ foreach($_GET AS $key => $value){ $$key = $value; } }//可以覆盖任意变量 ………… ………………………………………………………………………… 说这个是漏洞还太早了,要结合下面的代码看到底有没有好利用的地方,看config_base.php文件可以发现这样一段代码 ………………………………………………………………………… ………… //载入用户配置的系统变量 require_once(DEDEINC."/config_hand.php"); ………… if($phpold==1){ //低版本强制检查变量 $cfg_isMagic = false; $cfg_registerGlobals = false; }else{ $cfg_registerGlobals = @ini_get("register_globals"); $cfg_isMagic = @ini_get("magic_quotes_gpc"); } //检测系统是否注册外部变量 if(!$cfg_isMagic) require_once(DEDEINC."/config_rglobals_magic.php"); else if(!$cfg_registerGlobals || $cfg_needFilter) require_once(DEDEINC."/config_rglobals.php"); ………………………………………………………………………… 从这里可以看出,在register_globals=off...
这是一个比较有意思的东西,但是成功利用起来并不容易,呵呵。 首先看config_rglobals.php文件,摘的一段代码如下。这里作者本意是为了帮我们注册变量的,但是他却疏忽了我们不但能注册变量,还能覆盖一些变量。config_rglobals_magic.php也有同样的问题 ………………………………………………………………………… if(is_array($_GET)){ foreach($_GET AS $key => $value){ $$key = $value; } }//可以覆盖任意变量 ………… ………………………………………………………………………… 说这个是漏洞还太早了,要结合下面的代码看到底有没有好利用的地方,看config_base.php文件可以发现这样一段代码 ………………………………………………………………………… ………… //载入用户配置的系统变量 require_once(DEDEINC."/config_hand.php"); ………… if($phpold==1){ //低版本强制检查变量 $cfg_isMagic = false; $cfg_registerGlobals = false; }else{ $cfg_registerGlobals = @ini_get("register_globals"); $cfg_isMagic = @ini_get("magic_quotes_gpc"); } //检测系统是否注册外部变量 if(!$cfg_isMagic) require_once(DEDEINC."/config_rglobals_magic.php"); else if(!$cfg_registerGlobals || $cfg_needFilter) require_once(DEDEINC."/config_rglobals.php"); ………………………………………………………………………… 从这里可以看出,在register_globals=off 我们可以注册自己的变量并覆盖之前的值。而在register_globals=on时由于服务器配置的原因,ini_get()函数在很多时候是会失效的。简单的说,就是即使register_globals=On,也可能是ini_get('register_globals') =FALSE,所以依旧可以导致变量覆盖。但是能覆盖的只能是在这之前的内容,向前找看到config_hand.php文件里面定义的值似乎都能覆盖,但是真的能覆盖吗?再向前看到这样的代码,原来程序还是有考虑的 ………………………………………………………………………… //全局安全检测 foreach($ckvs as $ckv){ foreach($$ckv AS $_k => $_v){ if(eregi("^(globals|cfg_)",$_k)) unset(${$ckv}[$_k]); } } ……………………………………………………………………… 上面代码的意思是cfg_开头的变量不让从外部提交,发现了就unset掉,这样看的话config_hand.php里面cfg_开头的全局变量都是不让我们覆盖的。看到这里也许有人觉得没戏了。厄,多数情况下是这样的,但是别忘记了我们还有Zend_Hash_Del_Key_Or_Index漏洞,在PHP < 4.4.3, 5 <= PHP < 5.1.4时这个unset并不能释放我们的变量,于是这里就带来了隐患。 下面说个有意思的利用方式,就是选择覆盖$cfg_mediatype来上传任意文件呢?但是这个地方是有限制的,在config_base.php中用require_once函数调用文件config_rglobals.php之前有一段这样的代码 ……………………………………………………………… //检测上传的文件中是否有危险代码,有直接退出处理 if( !isset($cfg_NoUploadSafeCheck) ){ if (is_array($_FILES)) { foreach($_FILES AS $_name => $_value){ ${$_name} = $_value['tmp_name']; $_fp = @fopen(${$_name},'r'); $_fstr = @fread($_fp,filesize(${$_name})); @fclose($_fp); if($_fstr!='' && ereg("<(\?|%)",$_fstr)){ echo "你上传的文件中含有危险内容,程序终止处理!"; exit(); } } }} ………………………………………………………………… 只有$cfg_NoUploadSafeCheck非空才可以绕过这段检查但是由于在这段代码后才用函数require_once来调用文件config_rglobals.php注册变量,所以只有在php设置register_globals=on时我们才可以提交$cfg_NoUploadSafeCheck绕过过滤上传php脚本 下面我们来看如何具体利用,看文件 ………………………………………………………… \include\dialoguser\medias_upload.php ………… if(!CheckAddonType($uploadfile_name)){ ShowMsg("你所上传的文件类型被禁止,系统只允许上传<br>".$cfg_mb_mediatype." 类型附件!","-1"); exit(); } $fs = explode(".",$uploadfile_name); $sname = trim($fs[count($fs)-1]); if($sname==''){ ShowMsg("你所上传的文件无法识别,系统禁止上传<br />","-1"); exit(); } $nowtme = mytime(); $filename_name = dd2char($cfg_ml->M_ID."0".strftime("%y%m%d%H%M%S",$nowtme)."0".mt_rand(1000,9999)); $filename = $filename_name.".".$sname; //这里用不带目录的文件名作标题 $fileurl = $rootdir."/".$filename; $fullfilename = $cfg_basedir.$fileurl; //严格检查最终的文件名 if(!CheckAddonType($fullfilename) || eregi("\.(php|asp|pl|shtml|jsp|cgi|aspx)",$fullfilename)){ ShowMsg("你所上传的文件类型被禁止,系统只允许上传<br>".$cfg_mb_mediatype." 类型附件!","-1"); exit(); } @move_uploaded_file($uploadfile,$fullfilename); …… ………………………………………………………………………. 对于检查最终的文件名部分的代码,asa并不在黑名单里面。剩下的就是CheckAddonType函数的过滤了,我们找到相关代码 …………………………………………………………………… \\include\inc_memberlogin.php //检测用户的附件类型 function CheckAddonType($aname){ global $cfg_mb_mediatype; if(empty($cfg_mb_mediatype)){ $cfg_mb_mediatype = "jpg|gif|png|bmp|swf|mpg|mp3|rm|rmvb|wmv|asf|wma|zip|rar|doc|xsl|ppt|wps"; } $anames = explode('.',$aname); $atype = $anames[count($anames)-1]; if(count($anames)==1) return false; else{ $atype = strtolower($atype); $cfg_mb_mediatypes = explode('|',trim($cfg_mb_mediatype)); if(in_array($atype,$cfg_mb_mediatypes)) return true; else return false; } } …………………………………………………………………………….. 依然是依据$cfg_mb_mediatype来过滤的,综合上面的分析,可以将之覆盖为asa来达到我们的目的。实战中要利用起来真不容易,需要ini_get失效,register_globals 为on,php本身Zend_Hash_Del_Key_Or_Index的洞没有被修补,还有更不幸的是需要支持asa。 Dedecms V5 暂无