A-A+

XL某服务器svn源码泄露 可SQL 影响海量用户数据

2016年10月15日 14:33 漏洞安全 评论 1 条 共3265字 (阅读3,399 views次)

【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】

此文,在2016-04-23 12:28已经通过WOOYUN系统报告给XL,并且早已修复。所以这里公开。
其实挺简单的,无意中找到了一处 http://xxx.xxx.xxx.xxx:8080/.svn/entries
然后果断把源码下载下来。第一步直接看数据库文件配置:

XL某服务器数据库配置

XL某服务器数据库配置

数据库没有外联。咱们访问一下网站,地址:http://xxx.xxx.xxx.xxx:8080/exxxrt/Drixxxxpply 访问提示无权限。如图:

网站限制权限

网站限制权限

所以,咱们只能通过源码入手。下面咱们通过下载下来的源码审计一下。因为没有找到登录口,直接提示无权限,所以只能是查看一下源码,是如何限制的。如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    private $_domain = 'http://211.81.13.211:8080/';
    public function index() {
        $data['domain'] = $this->_domain;
        $data['left']=array(
            array(
                'name'=>'自驾游列表',
                'page'=>'exxxrt/Drixxxply/datalist'
            )
        );
        $this->load->view('exxxrt/index',$data);
    }
    private function _check(){
        $cross_ip_arr = array('211.81.5.211','127.0.0.1');
        $ip = ip();
        if(!in_array($ip,$cross_ip_arr)){
            echo '无权限';
            exit;
        }
        return true;
    }

从这里我好象懂了什么,,,。莫非,,,只允许IP 为'211.81.5.211','127.0.0.1' 这两的地址访问? 咱们直接X-Forwarded-For 然后访问试试。。。

成功进入网站

成功进入网站


看到了吧,成功进入网站!!!但是后台功能实在太简洁明了了。。。试着审计一下源码,看看能否深入利用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    public function datalist($curpage = 1) {
        $this->_check();
        $size = 50;
        $offset = intval($curpage) <= 0 ? 0 : (intval($curpage) - 1) * $size;
        $sql = "SELECT * FROM bizcar_drive_apply where 1=1";
        $sql .= $this->_param();                                          //echo  注意,下面没过滤的参数全部都传到了这里!!!
        $count = count($this->db->query($sql)->result_array());
        $sql .= " order by id desc";
        $sql = $sql . " limit " . $offset . "," . $size;
        $data['list'] = $this->db->query($sql)->result_array();
        $urls = array();
        foreach ($data['list'] as $k => $v) {
            $data['list'][$k]['car_name'] = $this->_getSubName($v['brand_id'], $v['sub_brand_id'], $v['car_id']);
            $area = $this->_getProvinceCity($v['province_id'], $v['city_id']);
            if (empty($urls[$v['article_id']])) {
                $tmp = $this->_getUrl($v['article_id']);
                if (!empty($tmp)) {
                    $urls[$v['article_id']] = $tmp;
                }
            }
            $data['list'][$k]['url'] = empty($urls[$v['article_id']]['url']) ? '' : $urls[$v['article_id']]['url'];
            $data['list'][$k]['area'] = implode('-', $area);
        }
        $json = $this->config->item('city_json');
        $data['area_json'] = $json;
        $data['area'] = json_decode($json, true);
 
        $config['num_tag_open'] = $config['prev_tag_open'] = $config['next_tag_open'] = $config['last_tag_open'] = $config['first_tag_open'] = '<li>';
        $config['num_tag_close'] = $config['prev_tag_close'] = $config['next_tag_close'] = $config['last_tag_end'] = $config['first_tag_close'] = '</li>';
        $config['cur_tag_open'] = '<li class="active"><a>';
        $config['cur_tag_close'] = "</li></a>";
        $config['reuse_query_string'] = true;
        $data['pages'] = create_page($this->_domain.'exxxrt/Drixxxxply/datalist', $count, $curpage, $size, 4, $config);
        $data['province_id'] = intval($this->input->get('province_id'));
        $data['city_id'] = intval($this->input->get('city_id'));
        $data['domain'] = $this->_domain;
        $data['left']=array(
            array(
                'name'=>'自驾游列表',
                'page'=>'exxxrt/Drivxxxxply/datalist'
            )
        );
        $this->load->view('exxxrt/temp_drive_apply_view', $data);
    }
 
    private function _param() {
        $article_title = $this->input->get('article_title');
        $user = $this->input->get('user');
        $user_mobile = $this->input->get('user_mobile');
        $start_time = $this->input->get('start_time');
        $end_time = $this->input->get('end_time');
        $province_id = intval($this->input->get('province_id'));
        $city_id = intval($this->input->get('city_id'));
        $ret = '';
        if (!empty($article_title)) {
            $ret .= " and article_title like '%" . trim($article_title) . "%'";
        }
        if (!empty($user)) {
            $ret .= " and user like '%" . trim($user) . "%'";
        }
        if (!empty($user_mobile)) {
            $ret .= " and user_mobile = '" . trim($user_mobile) . "'";
        }
 
        if (!empty($start_time)) {
            $ret .= " and date >= '" . $start_time . "'";
        }
        if (!empty($end_time)) {
            $ret .= " and date <= '" . $end_time . "'";
        }
        if ($province_id > 0) {
            $ret .= ' and province_id = ' . $province_id;
            if ($city_id > 0) {
                $ret .= ' and city_id = ' . $city_id;
            }
        }
 
        return $ret;     // 注意这里,这里把上面没过滤的参数的值组成SQL语句,返回
    }

基本完全没过滤啊。。。
$article_title = $this->input->get('article_title'); //此处完全没过滤
$user = $this->input->get('user'); //此处完全没过滤
$user_mobile = $this->input->get('user_mobile'); //此处完全没过滤
$start_time = $this->input->get('start_time'); //此处完全没过滤
$end_time = $this->input->get('end_time'); //此处完全没过滤
$province_id = intval($this->input->get('province_id')); //此处只能为数字
$city_id = intval($this->input->get('city_id')); //此处只能为数字

看上面,我已经说明了,那这么简单,就不麻烦了。。。。。。 下面愿意练习手工的就手工,不愿意的直接用工具。但是我表示。。。还是工具快点。。。
直接SQLMAP

sqlmap检测

sqlmap检测

然后发现有一个错误可以直接泄露路径!!如图:

XL分站泄露路径

XL分站泄露路径

但是可惜注入点权限限制的太严格,并没办法利用。 最后也只能这样作罢。。。好了,简单看一下数据量。
这里注意,千万不要脱裤做傻事哦。
back-end DBMS: MySQL 5.0

Database: weidealer

+-------------------+---------+

| Table | Entries |

+-------------------+---------+

| bizcar_user_trace | 3672849 |

| weixin_userinfo | 90723 |

| bizcar_admin_info | 46 |

+-------------------+---------+

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

1 条留言  访客:1 条  博主:0 条

  1. 路人甲

    你咋搜索到crm的。。

给我留言