if(!empty($newname)) { $filename = $newname; if(!ereg("\.", $filename)) $fs = explode('.', $uploadfile_name); else $fs = explode('.', $filename); if(eregi($cfg_not_allowall, $fs[count($fs)-1])) { ShowMsg("你指定的文件名被系统禁止!",'javascript:;'); exit(); }//虽然使用eregi函数进行正则判断,无法利用大写绕过,但是只要在变量 $newname值最后增加一个“.”,就可以绕过了。 if(!ereg("\.", $filename)) $filename = $filename.'.'.$fs[count($fs)-1]; } …(略)
只要我们在变量$newname 最后增加一个“.”,就可以绕过限制了,比如“myfile.php.”,
代 码获取的 文件扩展 名 “ $fs[count($fs)-1] ” 是空值 , 所以不 满足条 件 “eregi($cfg_not_allowall, $fs[count($fs)-1])”,因此页面不执行“exit()”继续上 传文件。 全局变量漏洞 由于 DeDeCMS 对全局变量限制不严格,导致可以外部提交全局变量,漏洞影响 2011 年 8 月 12 日升级之前 V5.7 和 5.6 所有版本。DeDeCMS 限制提交以“cfg_|GLOBALS”开头的变 量名,include/common.inc.php 相关代码如下: ============== 8 月 12 日升级前 =================== if (!defined('DEDEREQUEST')) { //检查和注册外部提交的变量 foreach($_REQUEST as $_k=>$_v) //语句① { if( strlen($_k)>0 && preg_match('/^(cfg_|GLOBALS)/',$_k) ) { exit('Request var not allow!'); } } foreach(Array('_GET','_POST','_COOKIE') as $_request) //语句② { foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v); } } ============== 8 月 12 日升级后 =================== if (!defined('DEDEREQUEST')) { //检查和注册外部提交的变量 (2011.8.10 修改登录时相关过滤) function CheckRequest(&$val) { if (is_array($val)) { foreach ($val as $_k=>$_v) { CheckRequest($_k); CheckRequest($val[$_k]); } } else { if( strlen($val)>0 && preg_match('#^(cfg_|GLOBALS)#',$val) ) { exit('Request var not allow!'); } } } CheckRequest($_REQUEST); foreach(Array('_GET','_POST','_COOKIE') as $_request) { foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v); } } 升级后增加了对提交变量名和值的过滤,我们分析升级前代码。语句①不允许$_REQUEST 方式提交“cfg_|GLOBALS”开头的变量名,由于 PHP 以数组方式存储变量,所以我们可以使 用“_POST[cfg_xxx]”方式进行提交。修改 tags.php 文件如下,观察输出的页面全局变量。 <?php /** * @version $Id: tags.php 1 2010-06-30 11:43:09Z tianya $ * @package DedeCMS.Site * @copyright Copyright (c) 2007 - 2010, DesDev, Inc. * @license http://help.dedecms.com/usersguide/license.html * @link http://www.dedecms.com */ require_once (dirname(__FILE__) . "/include/common.inc.php"); require_once (DEDEINC . "/arc.taglist.class.php"); $PageNo = 1; print_r($GLOBALS); exit; //增加这两行代码,输出全局变量 if(isset($_SERVER['QUERY_STRING'])) …(略) 在 URL 中提交:_POST[cfg_var]=Y,然后查看页面源码,观察_GET 和_POST 数组如图 10,当执行语句②后,_GET 数组中的变量被转为_POST 数组中,最后转为全局变量如图 11。 ![]() ![]()
分析 DeDeCMS 获取和注册变量的过程如下: if (!defined('DEDEREQUEST')) { |