zoukankan      html  css  js  c++  java
  • ECMall /app/buyer_groupbuy.app.php SQL Injection Vul

    catalog

    1. 漏洞描述
    2. 漏洞触发条件
    3. 漏洞影响范围
    4. 漏洞代码分析
    5. 防御方法
    6. 攻防思考

    1. 漏洞描述

    Relevant Link:


    2. 漏洞触发条件

    0x1: POC

    http://localhost/ecmall/index.php?app=buyer_groupbuy&act=exit_group&id=1 union select 1 from (select count(*),concat(floor(rand(0)*2),(select concat(user_name,password) from ecm_member limit 0,1))a from information_schema.tables group by a)b


    3. 漏洞影响范围
    4. 漏洞代码分析

    /app/buyer_groupbuy.app.php

    function exit_group()
    {
        //未对$id进行规范化过滤,导致攻击者可以传入非int型数据
        $id = empty($_GET['id']) ? 0 : $_GET['id'];
        if (!$id)
        {
            $this->show_warning('no_such_groupbuy');
            return false;
        }
    
        // 判断是否能退团
        if (!$this->_ican($id, ACT))
        {
            $this->show_warning('Hacking Attempt');
            return;
        }
        $member_mod = &m('member');
        $member_mod->unlinkRelation('join_groupbuy', $this->visitor->info['user_id'], $id);
        $this->show_message('exit_groupbuy_succeed');
    }

    跟进if (!$this->_ican($id, ACT))

    function _ican($id, $act = '')
    {
        $state_permission = array(
            GROUP_PENDING   => array(),
            GROUP_ON        => array('view', 'exit_group'),
            GROUP_END       => array('view'),
            GROUP_FINISHED  => array('view', 'buy'),
            GROUP_CANCELED  => array('view')
        );
    
        $group = current($this->_member_mod->getRelatedData('join_groupbuy', $this->visitor->info['user_id'], array(
            'conditions' => 'gb.group_id=' . $id,   //传入未过滤的$id参数 
            'order' => 'gb.group_id DESC',
            'fields' => 'gb.state,groupbuy_log.order_id'
        )));
        if (!$group)
        {
            return false; // 越权或没有该团购
        }
        else
        {
            $state_permission[GROUP_FINISHED] = $group['order_id'] > 0 ? array('view', 'view_order') : array('view', 'buy');
        }
        if (empty($act))
        {
            return $state_permission[$group['state']]; // 返回该团购此状态时允许的操作
        }
        return in_array($act, $state_permission[$group['state']]) ? true : false; // 该团购此状态是否允许执行此操作
    }

    继续跟进$this->_member_mod->getRelatedData
    /eccore/model/mode.base.php

    function getRelatedData($relation_name, $ids, $find_param = array())
    {
        $relation_info = $this->getRelation($relation_name);
        $model =& m($relation_info['model']);
        if (empty($ids))
        {
            $this->_error('no_ids_to_assoc', $model->getName());
    
            return false;
        }
    
        if ($relation_info['type'] != HAS_MANY && $relation_info['type'] != HAS_AND_BELONGS_TO_MANY)
        {
            $this->_error('invalid_assoc_model', $model->getName());
    
            return false;
        }
    
        $alias = $model->alias;
        /* 如果是多对多关系,则连接的表的别名为指定别名或中间表名,否则为模型的别名 */
        if ($relation_info['type'] == HAS_AND_BELONGS_TO_MANY)
        {
            $be_related = $model->getRelation($relation_info['reverse']);
            $alias = isset($be_related['alias']) ? $be_related['alias'] : $be_related['middle_table'];
        }
    
        /* 构造查询条件 */
        $conditions = $alias . '.' . $relation_info['foreign_key'] . ' ' . db_create_in($ids);   //主键值限定
        $conditions .= $relation_info['ext_limit'] ?
                    ' AND ' . $this->_getExtLimit($relation_info['ext_limit'], $alias)
                    : '';
        $conditions .= is_string($find_param['conditions']) ? ' AND ' . $find_param['conditions'] : '';
        $find_param['conditions'] = $conditions;
    
    
        /* 查询字段 */
        $find_param['fields'] = !empty($find_param['fields']) ?
                        $find_param['fields'] . ',' . $alias . '.' .$relation_info['foreign_key']
                        : '';
        switch ($relation_info['type'])
        {
            case HAS_MANY:
            break;
            case HAS_AND_BELONGS_TO_MANY:
            $find_param['join']   = !empty($find_param['join'])   ?
                            $find_param['join'] . ',' . $relation_info['reverse']
                            : $relation_info['reverse'];
            empty($find_param['order']) && $find_param['order'] = $model->alias . ".{$model->prikey} DESC";
            $find_param['index_key'] = array($relation_info['foreign_key'], $model->prikey);
            break;
        }
    
        return $model->find($find_param);
    }


    5. 防御方法

    /app/buyer_groupbuy.app.php

    function exit_group()
    {
        //通过intval进行规范化过滤
        //$id = empty($_GET['id']) ? 0 : $_GET['id'];
        $id = empty($_GET['id']) ? 0 : intval( $_GET['id'] );
        if (!$id)
        {
            $this->show_warning('no_such_groupbuy');
            return false;
        }
    
        // 判断是否能退团
        if (!$this->_ican($id, ACT))
        {
            $this->show_warning('Hacking Attempt');
            return;
        }
        $member_mod = &m('member');
        $member_mod->unlinkRelation('join_groupbuy', $this->visitor->info['user_id'], $id);
        $this->show_message('exit_groupbuy_succeed');
    }


    6. 攻防思考

    Copyright (c) 2015 LittleHann All rights reserved

  • 相关阅读:
    Kubernetes 部署 Kafka & Zookeeper & Kafka Manager
    prometheus-operator监控traefik-Ingress组件状态
    k8s与dns--coredns的一些实战经验
    kubernetes Tekton-CI/CD 持续集成流水线
    jenkins pipeline语法
    (Go)16.Redis连接池的使用
    (Go)15.golang printf 格式化输出
    (Go)14. 如何读取YAML,JSON,INI等配置文件
    Dubbo引用Javassist外部框架
    Dubbo之Filter 原理
  • 原文地址:https://www.cnblogs.com/LittleHann/p/4731091.html
Copyright © 2011-2022 走看看