Class: Metasploit::Framework::LoginScanner::ChefWebUI

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

Overview

The ChefWebUI HTTP LoginScanner class provides methods to authenticate to Chef WebUI

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

#session_idString

Returns Cookie value.

Returns:

  • (String)

    Cookie value



20
21
22
# File 'lib/metasploit/framework/login_scanner/chef_webui.rb', line 20

def session_id
  @session_id
end

#session_nameString

Returns Cookie name for session_id.

Returns:

  • (String)

    Cookie name for session_id



16
17
18
# File 'lib/metasploit/framework/login_scanner/chef_webui.rb', line 16

def session_name
  @session_name
end

Instance Method Details

#attempt_login(credential) ⇒ Result

Decides which login routine and returns the results

Parameters:

Returns:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/metasploit/framework/login_scanner/chef_webui.rb', line 26

def (credential)
  result_opts = {
    credential: credential,
    status: Metasploit::Model::Login::Status::INCORRECT,
    proof: nil,
    host: host,
    port: port,
    protocol: 'tcp'
  }

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

  Result.new(result_opts)
end

#check_setupObject



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/chef_webui.rb', line 47

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

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

    if res.body.to_s !~ /<title>Chef Server<\/title>/
      return "Unexpected HTTP body (is this really Chef WebUI?)"
    end

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

  false
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
83
# File 'lib/metasploit/framework/login_scanner/chef_webui.rb', line 73

def send_request(opts)
  res = super(opts)

  # Save the session ID cookie
  if res && res.get_cookies =~ /(_\w+_session)=([^;$]+)/i
    self.session_name = $1
    self.session_id = $2
  end

  res
end

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

Sends a login request

Parameters:

Returns:



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

def try_credential(csrf_token, credential)

  data  = "utf8=%E2%9C%93" # ✓
  data << "&authenticity_token=#{Rex::Text.uri_encode(csrf_token)}"
  data << "&name=#{Rex::Text.uri_encode(credential.public)}"
  data << "&password=#{Rex::Text.uri_encode(credential.private)}"
  data << "&commit=login"

  opts = {
    'uri'     => normalize_uri('/users/login_exec'),
    'method'  => 'POST',
    'data'    => data,
    'headers' => {
      'Content-Type'   => 'application/x-www-form-urlencoded',
      'Cookie'         => "#{self.session_name}=#{self.session_id}"
    }
  }

  send_request(opts)
end

#try_login(credential) ⇒ Hash

Tries to login to Chef WebUI

Parameters:

Returns:

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

    • :proof [String] the HTTP response body



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/metasploit/framework/login_scanner/chef_webui.rb', line 117

def (credential)

  # Obtain a CSRF token first
  res = send_request({
    'uri' => normalize_uri('/users/login')
  })
  unless (res && res.code == 200 && res.body =~ /input name="authenticity_token" type="hidden" value="([^"]+)"/m)
    return {:status => Metasploit::Model::Login::Status::UNTRIED, :proof => res.body}
  end

  csrf_token = $1

  res = try_credential(csrf_token, credential)
  if res && res.code == 302
    opts = {
      'uri'     => normalize_uri("/users/#{credential.public}/edit"),
      'method'  => 'GET',
      'headers' => {
        'Cookie'  => "#{self.session_name}=#{self.session_id}"
      }
    }
    res = send_request(opts)
    if (res && res.code == 200 && res.body.to_s =~ /New password for the User/)
      return {:status => Metasploit::Model::Login::Status::SUCCESSFUL, :proof => res.body}
    end
  end

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