Class: Dradis::Plugins::Nmap::Importer

Inherits:
Upload::Importer
  • Object
show all
Defined in:
lib/dradis/plugins/nmap/importer.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.templatesObject



3
4
5
# File 'lib/dradis/plugins/nmap/importer.rb', line 3

def self.templates
  {}
end

Instance Method Details

#import(params = {}) ⇒ Object

The framework will call this function if the user selects this plugin from the dropdown list and uploads a file.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/dradis/plugins/nmap/importer.rb', line 10

def import(params={})

  logger.info{ "Parsing Nmap output from #{ params[:file] }..." }
  doc = Nmap::XML::new(params[:file])
  logger.info{ 'Done.' }

  logger.info{ 'Validating Nmap output...' }
  if doc.hosts.empty?
    error = {
      'Title' => 'Invalid file format',
      'File name' => File.basename(params[:file]),
      'Description' => "The file you uploaded doesn't seem to be a valid Nmap XML file."
    }
    logger.fatal{ error['Description'] }
    error = error.map{|k,v| "#[%s]#\n%s\n" % [k, v] }.join("\n\n")
    content_service.create_note text: error
    return false
  end
  logger.info{ 'Done.' }

  # TODO: do something with the Nmap::Parser::Session information
  port_notes_to_add = {}

  doc.each_host do |host|
    host_label = host.ip
    host_node = content_service.create_node(label: host_label, type: :host)
    logger.info{ "New host: #{ host_label }" }

    # Set basic host properties
    host_node.set_property(:ip, host.ip)
    host_node.set_property(:hostname, host.hostnames.map(&:name)) if host.hostnames.present?
    host_node.set_property(:os, host.os.matches.map(&:name)) if host.os.present?

    # Old-style properties-in-a-note approach
    host_text = mapping_service.apply_mapping(source: 'host', data: host)
    content_service.create_note(text: host_text, node: host_node)

    host.each_port do |port|
      logger.info { "\tNew port: #{port.number}/#{port.protocol}" }

      service = {
        port: port.number,
        protocol: port.protocol.to_s,
        state: port.state.to_s,
        reason: port.reason,
        name: port.try(:service).try(:name),
        product: port.try(:service).try(:product),
        tunnel: port.try(:service).try(:ssl?) ? 'ssl' : 'n/a',
        version: port.try(:service).try(:version),
        source: :nmap,
      }

      # Node#set_service will store these under
      # Node#properties[:service_extras]:
      port.scripts.each { |k, v| service[k] = v } if port.try(:scripts)

      host_node.set_service(service)

      # HACK: patch in a `host` method to `Nmap::Port`
      # so we can use it in the template:
      port.class.module_eval { attr_accessor :host }
      port.host = host.ip

      # Add a note with the port information
      port_text = mapping_service.apply_mapping(source: 'port', data: port)
      content_service.create_note(
        text: port_text,
        node: host_node)
    end

    host_node.save
  end
end