Class: Metasploit::Framework::LoginScanner::Zabbix

Inherits:
HTTP
  • Object
show all
Defined in:
lib/metasploit/framework/login_scanner/zabbix.rb

Overview

The Zabbix HTTP LoginScanner class provides methods to do login routines for Zabbix 2.4 and 2.2 as well as versions 3, 4, and 5.

Constant Summary collapse

DEFAULT_PORT =
80
PRIVATE_TYPES =
[ :password ]

Constants inherited from HTTP

HTTP::AUTHORIZATION_HEADER, HTTP::DEFAULT_HTTP_NOT_AUTHED_CODES, HTTP::DEFAULT_HTTP_SUCCESS_CODES, HTTP::DEFAULT_REALM, HTTP::DEFAULT_SSL_PORT, HTTP::LIKELY_PORTS, HTTP::LIKELY_SERVICE_NAMES, HTTP::REALM_KEY

Instance Attribute Summary collapse

Attributes inherited from HTTP

#digest_auth_iis, #evade_header_folding, #evade_method_random_case, #evade_method_random_invalid, #evade_method_random_valid, #evade_pad_fake_headers, #evade_pad_fake_headers_count, #evade_pad_get_params, #evade_pad_get_params_count, #evade_pad_method_uri_count, #evade_pad_method_uri_type, #evade_pad_post_params, #evade_pad_post_params_count, #evade_pad_uri_version_count, #evade_pad_uri_version_type, #evade_shuffle_get_params, #evade_shuffle_post_params, #evade_uri_dir_fake_relative, #evade_uri_dir_self_reference, #evade_uri_encode_mode, #evade_uri_fake_end, #evade_uri_fake_params_start, #evade_uri_full_url, #evade_uri_use_backslashes, #evade_version_random_invalid, #evade_version_random_valid, #http_password, #http_success_codes, #http_username, #keep_connection_alive, #kerberos_authenticator_factory, #method, #ntlm_domain, #ntlm_send_lm, #ntlm_send_ntlm, #ntlm_send_spn, #ntlm_use_lm_key, #ntlm_use_ntlmv2, #ntlm_use_ntlmv2_session, #uri, #user_agent, #vhost

Instance Method Summary collapse

Methods inherited from HTTP

#authentication_required?

Instance Attribute Details

#versionString

Returns Product version.

Returns:

  • (String)

    Product version



17
18
19
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 17

def version
  @version
end

#zsessionString

Returns Cookie session.

Returns:

  • (String)

    Cookie session



21
22
23
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 21

def zsession
  @zsession
end

Instance Method Details

#attempt_login(credential) ⇒ Result

Decides which login routine and returns the results

Parameters:

Returns:



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 27

def (credential)
  result_opts = { credential: credential }

  begin
    status = (credential)
    result_opts.merge!(status)
  rescue ::EOFError, Rex::ConnectionError, ::Timeout::Error => e
    result_opts.merge!(status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e)
  end

  Result.new(result_opts)
end

#check_setupObject



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
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 42

def check_setup
  begin
    res = send_request({
      'uri' => normalize_uri('/')
    })
    return "Connection failed" if res.nil?

    if res.code != 200
      return "Unexpected HTTP response code #{res.code} (is this really Zabbix?)"
    end

    if res.body.to_s !~ /Zabbix ([^\s]+) Copyright .* by Zabbix/m # Regex check for older versions of Zabbix prior to version 3.
      if res.body.to_s !~ /href="http[sS]{0,1}:\/\/www\.zabbix\.com\/documentation\/(\d+\.\d+)\/">Help<\/a>/m
       return "Unexpected HTTP body (is this really Zabbix?)" # If both the regex for the old and new versions
                                                               # fail to match, the target likely isn't Zabbix.
      end
    end

    self.version = $1

  rescue ::EOFError, Errno::ETIMEDOUT, OpenSSL::SSL::SSLError, Rex::ConnectionError, ::Timeout::Error
    return "Unable to connect to target"
  end

  false
end

#perform_login_attempt(url) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 109

def (url)
  opts = {
    'uri'     => normalize_uri(url),
    'method'  => 'GET',
    'headers' => {
      'Cookie'  => "#{self.zsession}"
    }
  }
  send_request(opts)
end

#send_request(opts) ⇒ Rex::Proto::Http::Response

Sends a HTTP request with Rex

Returns:



73
74
75
76
77
78
79
80
81
82
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 73

def send_request(opts)
  res = super(opts)

  # Found a cookie? Set it. We're going to need it.
  if res && res.get_cookies =~ /(zbx_session(?:id)?=\w+(?:%3D){0,2};)/i
    self.zsession = $1
  end

  res
end

#try_credential(credential) ⇒ Rex::Proto::Http::Response

Sends a login request

Parameters:

Returns:



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 88

def try_credential(credential)

  data  = "request="
  data << "&name=#{Rex::Text.uri_encode(credential.public)}"
  data << "&password=#{Rex::Text.uri_encode(credential.private)}"
  data << "&autologin=1"
  data << "&enter=Sign%20in"

  opts = {
    'uri'     => normalize_uri('index.php'),
    'method'  => 'POST',
    'data'    => data,
    'headers' => {
      'Content-Type'   => 'application/x-www-form-urlencoded'
    }
  }

  send_request(opts)
end

#try_login(credential) ⇒ Hash

Tries to login to Zabbix

Parameters:

Returns:

  • (Hash)
    • :status [Metasploit::Model::Login::Status]

    • :proof [String] the HTTP response body



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/metasploit/framework/login_scanner/zabbix.rb', line 126

def (credential)
  begin
    res = try_credential(credential)

    if res && res.code == 302
      res = ('profile.php') # profile.php exists in Zabbix versions up to Zabbix 5.x
      if (res && res.code == 200 && res.body.to_s =~ /<title>.*: User profile<\/title>/)
        return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
      else
        res = ('/zabbix.php?action=userprofile.edit') # On version 5.x and later of Zabbix, profile.php was replaced with /zabbix.php?action=userprofile.edit
        if (res && res.code == 200 && res.body.to_s =~ /<title>.*: User profile<\/title>/)
          return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
        end
      end
    end

    {:status => Metasploit::Model::Login::Status::INCORRECT, :proof => res.body}

  rescue ::EOFError, Errno::ETIMEDOUT, Errno::ECONNRESET, Rex::ConnectionError, OpenSSL::SSL::SSLError, ::Timeout::Error => e
    return {:status => Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e}
  end
end