Skip to content

Commit d478df5

Browse files
committed
Merge remote-tracking branch 'rapid7/master'
Starting fresh.
2 parents f16ed32 + 214f337 commit d478df5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2533
-209
lines changed

lib/msf/core/exploit/exe.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def generate_payload_exe_service(opts = {})
7070
pl = opts[:code]
7171
pl ||= payload.encoded
7272

73-
if opts[:arch] and opts[:arch] == ARCH_X64
73+
if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == ARCH_X86_64)
7474
exe = Msf::Util::EXE.to_win64pe_service(framework, pl, opts)
7575
else
7676
exe = Msf::Util::EXE.to_win32pe_service(framework, pl, opts)
@@ -89,7 +89,7 @@ def generate_payload_dll(opts = {})
8989
pl = opts[:code]
9090
pl ||= payload.encoded
9191

92-
if opts[:arch] and opts[:arch] == ARCH_X64
92+
if opts[:arch] and (opts[:arch] == ARCH_X64 or opts[:arch] == ARCH_X86_64)
9393
dll = Msf::Util::EXE.to_win64pe_dll(framework, pl, opts)
9494
else
9595
dll = Msf::Util::EXE.to_win32pe_dll(framework, pl, opts)

lib/msf/core/exploit/http/server.rb

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ def initialize(info = {})
3636
], Exploit::Remote::HttpServer
3737
)
3838

39+
# Used to keep track of resources added to the service manager by
40+
# this module. see #add_resource and #cleanup
41+
@my_resources = []
3942
@service_path = nil
4043
end
4144

@@ -202,6 +205,39 @@ def start_service(opts = {})
202205
add_resource(uopts)
203206
end
204207

208+
# Set {#on_request_uri} to handle the given +uri+ in addition to the one
209+
# specified by the user in URIPATH.
210+
#
211+
# @note This MUST be called from {#primer} so that the service has been set
212+
# up but we have not yet entered the listen/accept loop.
213+
#
214+
# @param uri [String] The resource URI that should be handled by
215+
# {#on_request_uri}.
216+
# @return [void]
217+
def hardcoded_uripath(uri)
218+
proc = Proc.new do |cli, req|
219+
on_request_uri(cli, req)
220+
end
221+
222+
vprint_status("Adding hardcoded uri #{uri}")
223+
begin
224+
add_resource({'Path' => uri, 'Proc' => proc})
225+
rescue RuntimeError => e
226+
print_error("This module requires a hardcoded uri at #{uri}. Can't run while other modules are using it.")
227+
raise e
228+
end
229+
end
230+
231+
# Take care of removing any resources that we created
232+
def cleanup
233+
# Must dup here because remove_resource modifies @my_resources
234+
@my_resources.dup.each do |resource|
235+
remove_resource(resource)
236+
end
237+
238+
super
239+
end
240+
205241
#
206242
# Return a Hash containing a best guess at the actual browser and operating
207243
# system versions, based on the User-Agent header.
@@ -358,9 +394,16 @@ def report_user_agent(address, request, client_opts={})
358394
# NOTE: Calling #add_resource will change the results of subsequent calls
359395
# to #get_resource!
360396
#
397+
# @return (see Rex::Service#add_resource)
361398
def add_resource(opts)
362399
@service_path = opts['Path']
363-
service.add_resource(opts['Path'], opts)
400+
res = service.add_resource(opts['Path'], opts)
401+
402+
# This has to go *after* the call to service.add_resource in case
403+
# the service manager doesn't like it for some reason and raises.
404+
@my_resources.push(opts['Path'])
405+
406+
res
364407
end
365408

366409
#
@@ -455,7 +498,11 @@ def srvhost_addr
455498
# Removes a URI resource.
456499
#
457500
def remove_resource(name)
458-
service.remove_resource(name)
501+
# Guard against removing resources added by other modules
502+
if @my_resources.include?(name)
503+
@my_resources.delete(name)
504+
service.remove_resource(name)
505+
end
459506
end
460507

461508
#

lib/msf/core/module/reference.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ def initialize(in_ctx_id = 'Unknown', in_ctx_val = '')
9696
self.site = 'http://www.osvdb.org/' + in_ctx_val.to_s
9797
elsif (in_ctx_id == 'CVE')
9898
self.site = "http://cvedetails.com/cve/#{in_ctx_val.to_s}/"
99+
elsif (in_ctx_id == 'CWE')
100+
self.site = "http://cwe.mitre.org/data/definitions/#{in_ctx_val.to_s}.html"
99101
elsif (in_ctx_id == 'BID')
100102
self.site = 'http://www.securityfocus.com/bid/' + in_ctx_val.to_s
101103
elsif (in_ctx_id == 'MSB')

lib/msf/core/option_container.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def normalize(value)
173173

174174
def valid?(value=self.value)
175175
value = normalize(value)
176+
return false unless value.kind_of?(String) or value.kind_of?(NilClass)
176177
return false if empty_required_value?(value)
177178
return super
178179
end
@@ -263,6 +264,7 @@ def type
263264

264265
def valid?(value=self.value)
265266
return false if empty_required_value?(value)
267+
return true if value.nil? and !required?
266268

267269
(value and self.enums.include?(value.to_s))
268270
end
@@ -330,10 +332,17 @@ def type
330332

331333
def valid?(value)
332334
return false if empty_required_value?(value)
335+
return false unless value.kind_of?(String) or value.kind_of?(NilClass)
333336

334337
if (value != nil and value.empty? == false)
335338
begin
336-
::Rex::Socket.getaddress(value, true)
339+
getaddr_result = ::Rex::Socket.getaddress(value, true)
340+
# Covers a wierdcase where an incomplete ipv4 address will have it's
341+
# missing octets filled in with 0's. (e.g 192.168 become 192.0.0.168)
342+
# which does not feel like a legit behaviour
343+
if value =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
344+
return false unless value =~ Rex::Socket::MATCH_IPV4
345+
end
337346
rescue
338347
return false
339348
end
@@ -354,6 +363,7 @@ def type
354363
end
355364

356365
def normalize(value)
366+
return nil unless value.kind_of?(String)
357367
if (value =~ /^file:(.*)/)
358368
path = $1
359369
return false if not File.exists?(path) or File.directory?(path)
@@ -373,9 +383,12 @@ def normalize(value)
373383

374384
def valid?(value)
375385
return false if empty_required_value?(value)
386+
return false unless value.kind_of?(String) or value.kind_of?(NilClass)
376387

377388
if (value != nil and value.empty? == false)
378-
walker = Rex::Socket::RangeWalker.new(normalize(value))
389+
normalized = normalize(value)
390+
return false if normalized.nil?
391+
walker = Rex::Socket::RangeWalker.new(normalized)
379392
if (not walker or not walker.valid?)
380393
return false
381394
end
@@ -474,7 +487,7 @@ def valid?(value)
474487
Regexp.compile(value)
475488

476489
return true
477-
rescue RegexpError
490+
rescue RegexpError, TypeError
478491
return false
479492
end
480493
end

lib/msf/util/exe.rb

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -412,11 +412,9 @@ def self.to_win32pe_old(framework, code, opts={})
412412
pe = fd.read(fd.stat.size)
413413
}
414414

415-
if(payload.length < 2048)
415+
if(payload.length <= 2048)
416416
payload << Rex::Text.rand_text(2048-payload.length)
417-
end
418-
419-
if(payload.length > 2048)
417+
else
420418
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
421419
end
422420

@@ -461,7 +459,12 @@ def self.to_win32pe_exe_sub(framework, code, opts={})
461459

462460
bo = pe.index('PAYLOAD:')
463461
raise RuntimeError, "Invalid Win32 PE EXE subst template: missing \"PAYLOAD:\" tag" if not bo
464-
pe[bo, 8192] = [code].pack("a8192")
462+
463+
if (code.length <= 4096)
464+
pe[bo, code.length] = [code].pack("a*")
465+
else
466+
raise RuntimeError, "The EXE generator now has a max size of 4096 bytes, please fix the calling module"
467+
end
465468

466469
return pe
467470
end
@@ -479,7 +482,12 @@ def self.to_win64pe(framework, code, opts={})
479482

480483
bo = pe.index('PAYLOAD:')
481484
raise RuntimeError, "Invalid Win64 PE EXE template: missing \"PAYLOAD:\" tag" if not bo
482-
pe[bo, code.length] = code
485+
486+
if (code.length <= 4096)
487+
pe[bo, code.length] = [code].pack("a*")
488+
else
489+
raise RuntimeError, "The EXE generator now has a max size of 4096 bytes, please fix the calling module"
490+
end
483491

484492
return pe
485493
end
@@ -498,7 +506,12 @@ def self.to_win32pe_service(framework, code, opts={})
498506

499507
bo = pe.index('PAYLOAD:')
500508
raise RuntimeError, "Invalid Win32 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
501-
pe[bo, 8192] = [code].pack("a8192")
509+
510+
if (code.length <= 8192)
511+
pe[bo, code.length] = [code].pack("a*")
512+
else
513+
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
514+
end
502515

503516
if name
504517
bo = pe.index('SERVICENAME')
@@ -527,7 +540,12 @@ def self.to_win64pe_service(framework, code, opts={})
527540

528541
bo = pe.index('PAYLOAD:')
529542
raise RuntimeError, "Invalid Win64 PE Service EXE template: missing \"PAYLOAD:\" tag" if not bo
530-
pe[bo, 8192] = [code].pack("a8192")
543+
544+
if (code.length <= 8192)
545+
pe[bo, code.length] = [code].pack("a*")
546+
else
547+
raise RuntimeError, "The EXE generator now has a max size of 8192 bytes, please fix the calling module"
548+
end
531549

532550
if name
533551
bo = pe.index('SERVICENAME')
@@ -554,7 +572,12 @@ def self.to_win32pe_dll(framework, code, opts={})
554572

555573
bo = pe.index('PAYLOAD:')
556574
raise RuntimeError, "Invalid Win32 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
557-
pe[bo, 8192] = [code].pack("a8192")
575+
576+
if (code.length <= 2048)
577+
pe[bo, code.length] = [code].pack("a*")
578+
else
579+
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
580+
end
558581

559582
# optional mutex
560583
mt = pe.index('MUTEX!!!')
@@ -575,7 +598,12 @@ def self.to_win64pe_dll(framework, code, opts={})
575598

576599
bo = pe.index('PAYLOAD:')
577600
raise RuntimeError, "Invalid Win64 PE DLL template: missing \"PAYLOAD:\" tag" if not bo
578-
pe[bo, 8192] = [code].pack("a8192")
601+
602+
if (code.length <= 2048)
603+
pe[bo, code.length] = [code].pack("a*")
604+
else
605+
raise RuntimeError, "The EXE generator now has a max size of 2048 bytes, please fix the calling module"
606+
end
579607

580608
# optional mutex
581609
mt = pe.index('MUTEX!!!')

lib/rex/compat.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,11 @@ def self.open_browser(url='http://metasploit.com/')
131131
# Search through the PATH variable (if it exists) and chose a browser
132132
# We are making an assumption about the nature of "PATH" so tread lightly
133133
if defined? ENV['PATH']
134-
# "sensible-browser" opens the "default" browser in Ubuntu and others, so try that first
135-
# but also provide fallbacks
136-
['sensible-browser', 'firefox', 'opera', 'chromium-browser', 'konqueror'].each do |browser|
134+
# "xdg-open" is more general than "sensible-browser" and can be useful for lots of
135+
# file types -- text files, pcaps, or URLs. It's nearly always
136+
# going to use the application the user is expecting. If we're not
137+
# on something Debian-based, fall back to likely browsers.
138+
['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser|
137139
ENV['PATH'].split(':').each do |path|
138140
# Does the browser exists?
139141
if File.exists?("#{path}/#{browser}")
@@ -143,9 +145,6 @@ def self.open_browser(url='http://metasploit.com/')
143145
end
144146
end
145147
end
146-
147-
# If nothing else worked, default to firefox
148-
system("firefox #{url} &")
149148
end
150149
end
151150

lib/rex/exploitation/javascriptosdetect.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ window.os_detect.getVersion = function(){
4545
var version = "";
4646
var unknown_fingerprint = null;
4747

48+
var css_is_valid = function(prop, propCamelCase, css) {
49+
if (!document.createElement) return false;
50+
var d = document.createElement('div');
51+
d.setAttribute('style', prop+": "+css+";")
52+
return d.style[propCamelCase] === css;
53+
}
54+
4855
//--
4956
// Client
5057
//--
@@ -179,24 +186,56 @@ window.os_detect.getVersion = function(){
179186
if (!ua_version || 0 == ua_version.length) {
180187
ua_is_lying = true;
181188
}
182-
} else if (!document.all && navigator.taintEnabled) {
189+
} else if (!document.all && navigator.taintEnabled ||
190+
'MozBlobBuilder' in window) {
183191
// Use taintEnabled to identify FF since other recent browsers
184192
// implement window.getComputedStyle now. For some reason, checking for
185193
// taintEnabled seems to cause IE 6 to stop parsing, so make sure this
186194
// isn't IE first.
187-
//
195+
196+
// Also check MozBlobBuilder because FF 9.0.1 does not support taintEnabled
197+
188198
// Then this is a Gecko derivative, assume Firefox since that's the
189199
// only one we have sploits for. We may need to revisit this in the
190200
// future. This works for multi/browser/mozilla_compareto against
191201
// Firefox and Mozilla, so it's probably good enough for now.
192202
ua_name = clients_ff;
193203
// Thanks to developer.mozilla.org "Firefox for developers" series for most
194204
// of these.
195-
if ('mozConnection' in navigator) {
205+
// Release changelogs: http://www.mozilla.org/en-US/firefox/releases/
206+
if ('HTMLTimeElement' in window) {
207+
ua_version = '22.0'
208+
} else if ('createElement' in document &&
209+
document.createElement('main') &&
210+
document.createElement('main').constructor === window['HTMLElement']) {
211+
ua_version = '21.0'
212+
} else if ('imul' in Math) {
213+
ua_version = '20.0'
214+
} else if (css_is_valid('font-size', 'fontSize', '23vmax')) {
215+
ua_version = '19.0'
216+
} else if ('devicePixelRatio' in window) {
217+
ua_version = '18.0'
218+
} else if ('createElement' in document &&
219+
document.createElement('iframe') &&
220+
'sandbox' in document.createElement('iframe')) {
221+
ua_version = '17.0'
222+
} else if ('mozApps' in navigator && 'install' in navigator.mozApps) {
223+
ua_version = '16.0'
224+
} else if ('HTMLSourceElement' in window &&
225+
HTMLSourceElement.prototype &&
226+
'media' in HTMLSourceElement.prototype) {
227+
ua_version = '15.0'
228+
} else if ('mozRequestPointerLock' in document.body) {
229+
ua_version = '14.0'
230+
} else if ('Map' in window) {
231+
ua_version = "13.0"
232+
} else if ('mozConnection' in navigator) {
196233
ua_version = "12.0";
197234
} else if ('mozVibrate' in navigator) {
198235
ua_version = "11.0";
199-
} else if ('mozCancelFullScreen' in document) {
236+
} else if (css_is_valid('-moz-backface-visibility', 'MozBackfaceVisibility', 'hidden')) {
237+
ua_version = "10.0";
238+
} else if ('doNotTrack' in navigator) {
200239
ua_version = "9.0";
201240
} else if ('insertAdjacentHTML' in document.body) {
202241
ua_version = "8.0";
@@ -221,7 +260,6 @@ window.os_detect.getVersion = function(){
221260
} else {
222261
ua_version = "1";
223262
}
224-
225263
if (navigator.oscpu != navigator.platform) {
226264
ua_is_lying = true;
227265
}

0 commit comments

Comments
 (0)