Class: Msf::Plugin::Nexpose::NexposeCommandDispatcher

Inherits:
Object
  • Object
show all
Includes:
Ui::Console::CommandDispatcher
Defined in:
plugins/nexpose.rb

Instance Attribute Summary

Attributes included from Ui::Console::CommandDispatcher

#driver

Attributes included from Rex::Ui::Text::DispatcherShell::CommandDispatcher

#shell, #tab_complete_items

Instance Method Summary collapse

Methods included from Ui::Console::CommandDispatcher

#active_module, #active_module=, #active_session, #active_session=, #build_range_array, #docs_dir, #framework, #initialize, #load_config, #log_error, #remove_lines

Methods included from Rex::Ui::Text::DispatcherShell::CommandDispatcher

#cmd_help, #cmd_help_help, #cmd_help_tabs, #deprecated_cmd, #deprecated_commands, #deprecated_help, #docs_dir, #help_to_s, included, #initialize, #print, #print_error, #print_good, #print_line, #print_status, #print_warning, #tab_complete_directory, #tab_complete_filenames, #tab_complete_generic, #tab_complete_source_address, #unknown_command, #update_prompt

Instance Method Details

#cmd_nexpose_activity(*_args) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'plugins/nexpose.rb', line 187

def cmd_nexpose_activity(*_args)
  return if !nexpose_verify

  scans = @nsc.scan_activity || []
  case scans.length
  when 0
    print_status('There are currently no active scan jobs on this Nexpose instance')
  when 1
    print_status('There is 1 active scan job on this Nexpose instance')
  else
    print_status("There are currently #{scans.length} active scan jobs on this Nexpose instance")
  end

  scans.each do |scan|
    print_status("    Scan ##{scan.scan_id} is running on Engine ##{scan.engine_id} against site ##{scan.site_id} since #{scan.start_time}")
  end
end

#cmd_nexpose_command(*args) ⇒ Object



249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'plugins/nexpose.rb', line 249

def cmd_nexpose_command(*args)
  return if !nexpose_verify

  if args.empty?
    print_error('No command was specified')
    return
  end

  res = @nsc.console_command(args.join(' ')) || ''

  print_status('Command Output')
  print_line(res)
  print_line('')
end

#cmd_nexpose_connect(*args) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'plugins/nexpose.rb', line 87

def cmd_nexpose_connect(*args)
  return if !nexpose_verify_db

  if !args[0] && ::File.readable?(Nexpose_yaml.to_s)
    lconfig = YAML.load_file(Nexpose_yaml.to_s)
    @user = lconfig['default']['username']
    @pass = lconfig['default']['password']
    @host = lconfig['default']['server']
    @port = lconfig['default']['port']
    @trust_cert = lconfig['default']['trust_cert']
    unless @trust_cert
      @sslv = 'ok' # TODO: Not super-thrilled about bypassing the SSL warning...
    end
    
    return
  end

  if (args.empty? || args[0].empty? || (args[0] == '-h'))
    nexpose_usage
    return
  end

  @user = @pass = @host = @port = @sslv = @trust_cert = @trust_cert_file = nil

  case args.length
  when 1, 2
    cred, _split, targ = args[0].rpartition('@')
    @user, @pass = cred.split(':', 2)
    targ ||= '127.0.0.1:3780'
    @host, @port = targ.split(':', 2)
    @port ||= '3780'
    unless args.length == 1
      @trust_cert_file = args[1]
      if File.exist? @trust_cert_file
        @trust_cert = File.read(@trust_cert_file)
      else
        @sslv = @trust_cert_file
      end
    end
  when 4, 5
    @user, @pass, @host, @port, @trust_cert = args
    unless args.length == 4
      @trust_cert_file = @trust_cert
      if File.exist? @trust_cert_file
        @trust_cert = File.read(@trust_cert_file)
      else
        @sslv = @trust_cert_file
      end
    end
  else
    nexpose_usage
    return
  end
  
end

#cmd_nexpose_disconnect(*_args) ⇒ Object



596
597
598
599
# File 'plugins/nexpose.rb', line 596

def cmd_nexpose_disconnect(*_args)
  @nsc.logout if @nsc
  @nsc = nil
end

#cmd_nexpose_discover(*args) ⇒ Object



328
329
330
331
332
333
# File 'plugins/nexpose.rb', line 328

def cmd_nexpose_discover(*args)
  args << '-h' if args.empty?
  args << '-t'
  args << 'aggressive-discovery'
  cmd_nexpose_scan(*args)
end

#cmd_nexpose_dos(*args) ⇒ Object



342
343
344
345
346
347
# File 'plugins/nexpose.rb', line 342

def cmd_nexpose_dos(*args)
  args << '-h' if args.empty?
  args << '-t'
  args << 'dos-audit'
  cmd_nexpose_scan(*args)
end

#cmd_nexpose_exhaustive(*args) ⇒ Object



335
336
337
338
339
340
# File 'plugins/nexpose.rb', line 335

def cmd_nexpose_exhaustive(*args)
  args << '-h' if args.empty?
  args << '-t'
  args << 'exhaustive-audit'
  cmd_nexpose_scan(*args)
end

#cmd_nexpose_report_templates(*_args) ⇒ Object



239
240
241
242
243
244
245
246
247
# File 'plugins/nexpose.rb', line 239

def cmd_nexpose_report_templates(*_args)
  return if !nexpose_verify

  res = @nsc.list_report_templates || []

  res.each do |report|
    print_status("    Template: #{report.id} Name: '#{report.name}' Description: #{report.description}")
  end
end

#cmd_nexpose_save(*args) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'plugins/nexpose.rb', line 61

def cmd_nexpose_save(*args)
  # if we are logged in, save session details to nexpose.yaml
  if args[0] == '-h'
    print_status('Usage: ')
    print_status('       nexpose_save')
    return
  end

  if args[0]
    print_status('Usage: ')
    print_status('       nexpose_save')
    return
  end

  group = 'default'

  if ((@user && !@user.empty?) && (@host && !@host.empty?) && (@port && !@port.empty? && (@port.to_i > 0)) && (@pass && !@pass.empty?))
    config = { group.to_s => { 'username' => @user, 'password' => @pass, 'server' => @host, 'port' => @port, 'trust_cert' => @trust_cert } }
    ::File.open(Nexpose_yaml.to_s, 'wb') { |f| f.puts YAML.dump(config) }
    print_good("#{Nexpose_yaml} created.")
  else
    print_error('Missing username/password/server/port - relogin and then try again.')
    return
  end
end

#cmd_nexpose_scan(*args) ⇒ Object



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
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
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
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
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
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
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
# File 'plugins/nexpose.rb', line 349

def cmd_nexpose_scan(*args)
  opts = Rex::Parser::Arguments.new(
    '-h' => [ false, 'This help menu'],
    '-t' => [ true, 'The scan template to use (default:pentest-audit options:full-audit,exhaustive-audit,discovery,aggressive-discovery,dos-audit)'],
    '-c' => [ true, 'Specify credentials to use against these targets (format is type:user:pass'],
    '-n' => [ true, 'The maximum number of IPs to scan at a time (default is 32)'],
    '-s' => [ true, 'The directory to store the raw XML files from the Nexpose instance (optional)'],
    '-P' => [ false, 'Leave the scan data on the server when it completes (this counts against the maximum licensed IPs)'],
    '-v' => [ false, 'Display diagnostic information about the scanning process'],
    '-d' => [ false, 'Scan hosts based on the contents of the existing database'],
    '-I' => [ true, 'Only scan systems with an address within the specified range'],
    '-E' => [ true, 'Exclude hosts in the specified range from the scan']
  )

  opt_template = 'pentest-audit'
  opt_maxaddrs = 32
  opt_verbose = false
  opt_savexml = nil
  opt_preserve = false
  opt_rescandb = false
  opt_addrinc = nil
  opt_addrexc = nil
  opt_scanned = []
  opt_credentials = []

  opt_ranges = []

  opts.parse(args) do |opt, _idx, val|
    case opt
    when '-h'
      print_line('Usage: nexpose_scan [options] <Target IP Ranges>')
      print_line(opts.usage)
      return
    when '-t'
      opt_template = val
    when '-n'
      opt_maxaddrs = val.to_i
    when '-s'
      opt_savexml = val
    when '-c'
      if (val =~ /^([^:]+):([^:]+):(.+)/)
        type = Regexp.last_match(1)
        user = Regexp.last_match(2)
        pass = Regexp.last_match(3)
        msfid = Time.now.to_i
        newcreds = Nexpose::SiteCredentials.for_service("Metasploit Site Credential #{msfid}", nil, nil, nil, nil, type)
        newcreds.user_name = user
        newcreds.password = pass
        opt_credentials << newcreds
      else
        print_error("Unrecognized Nexpose scan credentials: #{val}")
        return
      end
    when '-v'
      opt_verbose = true
    when '-P'
      opt_preserve = true
    when '-d'
      opt_rescandb = true
    when '-I'
      opt_addrinc = OptAddressRange.new('TEMPRANGE', [ true, '' ]).normalize(val)
    when '-E'
      opt_addrexc = OptAddressRange.new('TEMPRANGE', [ true, '' ]).normalize(val)
    else
      opt_ranges << val
    end
  end

  return if !nexpose_verify

  # Include all database hosts as scan targets if specified
  if opt_rescandb
    print_status('Loading scan targets from the active database...') if opt_verbose
    framework.db.hosts.each do |host|
      next if host.state != ::Msf::HostState::Alive

      opt_ranges << host.address
    end
  end

  possible_files = opt_ranges # don't allow DOS by circular reference
  possible_files.each do |file|
    next unless ::File.readable? file

    print_status "Parsing ranges from #{file}"
    range_list = ::File.open(file, 'rb') { |f| f.read f.stat.size }
    range_list.each_line { |subrange| opt_ranges << subrange }
    opt_ranges.delete(file)
  end

  opt_ranges = opt_ranges.join(' ')

  if opt_ranges.strip.empty?
    print_line('Usage: nexpose_scan [options] <Target IP Ranges>')
    print_line(opts.usage)
    return
  end

  if opt_verbose
    print_status("Creating a new scan using template #{opt_template} and #{opt_maxaddrs} concurrent IPs against #{opt_ranges}")
  end

  range_inp = ::Msf::OptAddressRange.new('TEMPRANGE', [ true, '' ]).normalize(opt_ranges)
  range = ::Rex::Socket::RangeWalker.new(range_inp)
  include_range = opt_addrinc ? ::Rex::Socket::RangeWalker.new(opt_addrinc) : nil
  exclude_range = opt_addrexc ? ::Rex::Socket::RangeWalker.new(opt_addrexc) : nil

  completed = 0
  total = range.num_ips
  count = 0

  print_status("Scanning #{total} addresses with template #{opt_template} in sets of #{opt_maxaddrs}")

  while (completed < total)
    count += 1
    queue = []

    while ((ip = range.next_ip) && (queue.length < opt_maxaddrs))

      if (exclude_range && exclude_range.include?(ip))
        print_status(" >> Skipping host #{ip} due to exclusion") if opt_verbose
        next
      end

      if (include_range && !include_range.include?(ip))
        print_status(" >> Skipping host #{ip} due to inclusion filter") if opt_verbose
        next
      end

      opt_scanned << ip
      queue << ip
    end

    break if queue.empty?

    print_status("Scanning #{queue[0]}-#{queue[-1]}...") if opt_verbose

    msfid = Time.now.to_i

    # Create a temporary site
    site = Nexpose::Site.new(nil, opt_template)
    site.name = "Metasploit-#{msfid}"
    site.description = 'Autocreated by the Metasploit Framework'
    site.included_addresses = queue
    site.site_credentials = opt_credentials
    site.save(@nsc)

    print_status(" >> Created temporary site ##{site.id}") if opt_verbose

    report_formats = ['raw-xml-v2', 'ns-xml']
    report_format = report_formats.shift

    report = Nexpose::ReportConfig.build(@nsc, site.id, site.name, opt_template, report_format, true)
    report.delivery = Nexpose::Delivery.new(true)

    begin
      report.format = report_format
      report.save(@nsc, true)
    rescue ::Exception => e
      report_format = report_formats.shift
      if report_format
        retry
      end
      raise e
    end

    print_status(" >> Created temporary report configuration ##{report.id}") if opt_verbose

    # Run the scan
    begin
      res = site.scan(@nsc)
    rescue Nexpose::APIError => e
      nexpose_error_message = e.message
      nexpose_error_message.gsub!(/NexposeAPI: Action failed: /, '')
      print_error nexpose_error_message.to_s
      return
    end

    sid = res.id

    print_status(" >> Scan has been launched with ID ##{sid}") if opt_verbose

    rep = true
    begin
      prev = nil
      while true
        info = @nsc.scan_statistics(sid)
        break if info.status != 'running'

        stat = "Found #{info.nodes.live} devices and #{info.nodes.dead} unresponsive"
        if (stat != prev) && opt_verbose
          print_status(" >> #{stat}")
        end
        prev = stat
        select(nil, nil, nil, 5.0)
      end
      print_status(" >> Scan has been completed with ID ##{sid}") if opt_verbose
    rescue ::Interrupt
      rep = false
      print_status(" >> Terminating scan ID ##{sid} due to console interrupt") if opt_verbose
      @nsc.stop_scan(sid)
      break
    end

    # Wait for the automatic report generation to complete
    if rep
      print_status(' >> Waiting on the report to generate...') if opt_verbose
      last_report = nil
      until last_report
        last_report = @nsc.last_report(report.id)
        select(nil, nil, nil, 1.0)
      end
      url = last_report.uri

      print_status(' >> Downloading the report data from Nexpose...') if opt_verbose
      data = @nsc.download(url)

      if opt_savexml
        ::FileUtils.mkdir_p(opt_savexml)
        path = ::File.join(opt_savexml, "nexpose-#{msfid}-#{count}.xml")
        print_status(" >> Saving scan data into #{path}") if opt_verbose
        ::File.open(path, 'wb') { |fd| fd.write(data) }
      end

      process_nexpose_data(report_format, data)
    end

    next if opt_preserve

    # Make sure the scan has finished clean up before attempting to delete the site
    loop do
      info = @nsc.scan_statistics(sid)
      break if info.status == 'stopped' || info.status == 'finished'

      select(nil, nil, nil, 5.0)
    end
    print_status(' >> Deleting the temporary site and report...') if opt_verbose
    begin
      @nsc.delete_site(site.id)
    rescue ::Nexpose::APIError => e
      print_status(" >> Deletion of temporary site and report failed: #{e.inspect}")
    end
  end

  print_status("Completed the scan of #{total} addresses")
end

#cmd_nexpose_site_devices(*args) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'plugins/nexpose.rb', line 219

def cmd_nexpose_site_devices(*args)
  return if !nexpose_verify

  site_id = args.shift
  if !site_id
    print_error('No site ID was specified')
    return
  end

  devices = @nsc.list_site_devices(site_id) || []
  case devices.length
  when 0
    print_status('There are currently no devices within this site')
  end

  devices.each do |device|
    print_status("    Host: #{device.address} ID: #{device.id} Risk Factor: #{device.risk_factor} Risk Score: #{device.risk_score}")
  end
end

#cmd_nexpose_site_import(*args) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'plugins/nexpose.rb', line 284

def cmd_nexpose_site_import(*args)
  site_id = args.shift
  if !site_id
    print_error('No site ID was specified')
    return
  end

  msfid = Time.now.to_i

  report_formats = ['raw-xml-v2', 'ns-xml']
  report_format = report_formats.shift

  report = Nexpose::ReportConfig.build(@nsc, site_id, "Metasploit Export #{msfid}", 'pentest-audit', report_format, true)
  report.delivery = Nexpose::Delivery.new(true)

  begin
    report.format = report_format
    report.save(@nsc)
  rescue ::Exception => e
    report_format = report_formats.shift
    if report_format
      retry
    end
    raise e
  end

  print_status('Generating the export data file...')
  last_report = nil
  until last_report
    last_report = @nsc.last_report(report.id)
    select(nil, nil, nil, 1.0)
  end
  url = last_report.uri

  print_status('Downloading the export data...')
  data = @nsc.download(url)

  # Delete the temporary report ID
  @nsc.delete_report_config(report.id)

  print_status('Importing Nexpose data...')
  process_nexpose_data(report_format, data)
end

#cmd_nexpose_sites(*_args) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'plugins/nexpose.rb', line 205

def cmd_nexpose_sites(*_args)
  return if !nexpose_verify

  sites = @nsc.list_sites || []
  case sites.length
  when 0
    print_status('There are currently no active sites on this Nexpose instance')
  end

  sites.each do |site|
    print_status("    Site ##{site.id} '#{site.name}' Risk Factor: #{site.risk_factor} Risk Score: #{site.risk_score}")
  end
end

#cmd_nexpose_sysinfo(*_args) ⇒ Object



264
265
266
267
268
269
270
271
272
273
# File 'plugins/nexpose.rb', line 264

def cmd_nexpose_sysinfo(*_args)
  return if !nexpose_verify

  res = @nsc.system_information

  print_status('System Information')
  res.each_pair do |k, v|
    print_status("    #{k}: #{v}")
  end
end

#commandsObject



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'plugins/nexpose.rb', line 16

def commands
  {
    'nexpose_connect' => 'Connect to a running Nexpose instance ( user:pass@host[:port] )',
    'nexpose_save' => 'Save credentials to a Nexpose instance',
    'nexpose_activity' => 'Display any active scan jobs on the Nexpose instance',

    'nexpose_scan' => 'Launch a Nexpose scan against a specific IP range and import the results',
    'nexpose_discover' => 'Launch a scan but only perform host and minimal service discovery',
    'nexpose_exhaustive' => 'Launch a scan covering all TCP ports and all authorized safe checks',
    'nexpose_dos' => 'Launch a scan that includes checks that can crash services and devices (caution)',

    'nexpose_disconnect' => 'Disconnect from an active Nexpose instance',

    'nexpose_sites' => 'List all defined sites',
    'nexpose_site_devices' => 'List all discovered devices within a site',
    'nexpose_site_import' => 'Import data from the specified site ID',
    'nexpose_report_templates' => 'List all available report templates',
    'nexpose_command' => 'Execute a console command on the Nexpose instance',
    'nexpose_sysinfo' => 'Display detailed system information about the Nexpose instance'

    # @TODO:
    # nexpose_stop_scan
  }
end

#nameObject



12
13
14
# File 'plugins/nexpose.rb', line 12

def name
  'Nexpose'
end

#nexpose_compatibility_checkObject



275
276
277
278
279
280
281
282
# File 'plugins/nexpose.rb', line 275

def nexpose_compatibility_check
  res = @nsc.console_command('ver')
  if res !~ /^(NSC|Console) Version ID:\s*4[89]0\s*$/m
    print_error('')
    print_error('Warning: This version of Nexpose has not been tested with Metasploit!')
    print_error('')
  end
end

#nexpose_loginObject



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'plugins/nexpose.rb', line 150

def 
  if !((@user && !@user.empty?) && (@host && !@host.empty?) && (@port && !@port.empty? && (@port.to_i > 0)) && (@pass && !@pass.empty?))
    nexpose_usage
    return
  end

  if ((@host != 'localhost') && (@host != '127.0.0.1') && (@trust_cert.nil? && @sslv != 'ok'))
    # consider removing this message and replacing with check on trust_store, and if trust_store is not found validate @host already has a truly trusted cert?
    print_error('Warning: SSL connections are not verified in this release, it is possible for an attacker')
    print_error('         with the ability to man-in-the-middle the Nexpose traffic to capture the Nexpose')
    print_error("         credentials. If you are running this on a trusted network, please pass in 'ok'")
    print_error('         as an additional parameter to this command.')
    return
  end

  # Wrap this so a duplicate session does not prevent a new login
  begin
    cmd_nexpose_disconnect
  rescue ::Interrupt
    raise $ERROR_INFO
  rescue ::Exception
  end

  begin
    print_status("Connecting to Nexpose instance at #{@host}:#{@port} with username #{@user}...")
    nsc = Nexpose::Connection.new(@host, @user, @pass, @port, nil, nil, @trust_cert)
    nsc.
  rescue ::Nexpose::APIError => e
    print_error("Connection failed: #{e.reason}")
    return
  end

  @nsc = nsc
  nexpose_compatibility_check
  nsc
end

#nexpose_usageObject



143
144
145
146
147
148
# File 'plugins/nexpose.rb', line 143

def nexpose_usage
  print_status('Usage: ')
  print_status('       nexpose_connect username:password@host[:port] <ssl-confirm || trusted_cert_file>')
  print_status('        -OR- ')
  print_status('       nexpose_connect username password host port <ssl-confirm || trusted_cert_file>')
end

#nexpose_verifyObject



50
51
52
53
54
55
56
57
58
59
# File 'plugins/nexpose.rb', line 50

def nexpose_verify
  return false if !nexpose_verify_db

  if !@nsc
    print_error("No active Nexpose instance has been configured, please use 'nexpose_connect'")
    return false
  end

  true
end

#nexpose_verify_dbObject



41
42
43
44
45
46
47
48
# File 'plugins/nexpose.rb', line 41

def nexpose_verify_db
  if !(framework.db && framework.db.usable && framework.db.active)
    print_error('No database has been configured, please use db_connect first')
    return false
  end

  true
end

#nexpose_vuln_lookup(doc, vid, refs, host, serv = nil) ⇒ Object

Nexpose vuln lookup



615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
# File 'plugins/nexpose.rb', line 615

def nexpose_vuln_lookup(doc, vid, refs, host, serv = nil)
  doc.elements.each("/NexposeReport/VulnerabilityDefinitions/vulnerability[@id = '#{vid}']]") do |vulndef|
    title = vulndef.attributes['title']
    # pci_severity = vulndef.attributes['pciSeverity']
    # cvss_score = vulndef.attributes['cvssScore']
    # cvss_vector = vulndef.attributes['cvssVector']

    vulndef.elements['references'].elements.each('reference') do |ref|
      if ref.attributes['source'] == 'BID'
        refs['BID-' + ref.text] = true
      elsif ref.attributes['source'] == 'CVE'
        # ref.text is CVE-$ID
        refs[ref.text] = true
      elsif ref.attributes['source'] == 'MS'
        refs['MSB-MS-' + ref.text] = true
      end
    end

    refs['NEXPOSE-' + vid.downcase] = true

    vuln = framework.db.find_or_create_vuln(
      host: host,
      service: serv,
      name: 'NEXPOSE-' + vid.downcase,
      data: title
    )

    rids = []
    refs.each_key do |r|
      rids << framework.db.find_or_create_ref(name: r)
    end

    vuln.refs << (rids - vuln.refs)
  end
end

#process_nexpose_data(fmt, data) ⇒ Object



601
602
603
604
605
606
607
608
609
610
# File 'plugins/nexpose.rb', line 601

def process_nexpose_data(fmt, data)
  case fmt
  when 'raw-xml-v2'
    framework.db.import({ data: data })
  when 'ns-xml'
    framework.db.import({ data: data })
  else
    print_error("Unsupported Nexpose data format: #{fmt}")
  end
end