文章目錄

分析maccms的历史漏洞,发现在大量白帽子的洗礼下,安全性的提升还是很快的。尤其是引入360_safe3.

1

php导致漏洞的利用成本增加。记录一下分析相关代码的过程。。在最新版中这些漏洞都已经修复了。而且最新版的360也开始检测urldecode之前的变量是否存在危险字符了。

function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq)
{
    $errmsg = "<div style=\"position:fixed;top:0px;width:100%;height:100%;background-color:white;color:green;font-weight:bold;border-bottom:5px solid #999;\"><br>您的提交带有不合法参数,谢谢合作!<br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."</div>";
    $StrFiltValue=arr_foreach($StrFiltValue);
    $StrFiltValue=urldecode($StrFiltValue);

由于%a0导致的绕过,360已经开始检测

UNION([\s\S]*?)SELECT

只要出现unionselect就会拦截。导致绕过难度加大。

http://www.wooyun.org/bugs/wooyun-2014-066661

maccms入口文件 index.php前面就有个很显眼的urldecode.

if(!file_exists('inc/install.lock')) { echo '<script>location.href=\'install.php\';</script>';exit; }
    define('MAC_MODULE','home');
    require("inc/conn.php");
    require(MAC_ROOT.'/inc/common/360_safe3.php');
    $m = be('get','m');
    if(strpos($m,'.')){ $m = substr($m,0,strpos($m,'.')); }
    $par = explode('-',$m);
    $parlen = count($par);
    $ac = $par[0];

    if(empty($ac)){ $ac='vod'; $method='index'; }

    $colnum = array("id","pg","year","typeid","class","classid");
    if($parlen>=2){
        $method = $par[1];
         for($i=2;$i<$parlen;$i+=2){
            $tpl->P[$par[$i]] = in_array($par[$i],$colnum) ? intval($par[$i+1]) : urldecode($par[$i+1]);
            echo $tpl->P[$par[$i]];
        }
    }

在做了全局addslash的防御策略的cms中编解码是绕过addslash的一种常见的途径。

1

这个案例还是很经典的。跟踪be函数可以看到,通过be函数获取输入。只是对GET和POST做了addslash.

function be($mode,$key,$sp=',')
{
    ini_set("magic_quotes_runtime", 0);
    $magicq= get_magic_quotes_gpc();
    switch($mode)
    {
        case 'post':
            $res=isset($_POST[$key]) ? $magicq?$_POST[$key]:@addslashes($_POST[$key]) : '';
            break;
        case 'get':
            $res=isset($_GET[$key]) ? $magicq?$_GET[$key]:@addslashes($_GET[$key]) : '';
            break;
        case 'arr':
            $arr =isset($_POST[$key]) ? $_POST[$key] : '';
            if($arr==""){
                $value="0";
            }
            else{
                for($i=0;$i<count($arr);$i++){
                    $res=implode($sp,$arr);
                } 
            }
            break;
        default:
            $res=isset($_REQUEST[$key]) ? $magicq ? $_REQUEST[$key] : @addslashes($_REQUEST[$key]) : '';
            break;
    }
    return $res;
}

所以对从cookie获取输入,以及使用be(‘arr’)方式获取输入都是没有过滤的点。

修复方案采用的是对url解码之后做了一次转义,当时这不是一个最完美的安全编码方式,虽然他解决了这个url解码导致的绕过。

foreach($tpl->P as $k=>$v){
    if(!is_numeric($v)){
        $tpl->P[$k] = mysql_real_escape_string($v);
    }
}

个人微信公众号

文章目錄