class Rex::Parser::NmapDocument
Public Instance Methods
better_os_match(orig_hash,new_hash)
click to toggle source
Compare OS fingerprinting data
# File lib/rex/parser/nmap_nokogiri.rb, line 25 def better_os_match(orig_hash,new_hash) return false unless new_hash.has_key? "accuracy" return true unless orig_hash.has_key? "accuracy" new_hash["accuracy"].to_i > orig_hash["accuracy"].to_i end
collect_host_data()
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 229 def collect_host_data if @state[:host_alive] @report_data[:state] = Msf::HostState::Alive else @report_data[:state] = Msf::HostState::Dead end if @state[:addresses] if @state[:addresses].has_key? "ipv4" @report_data[:host] = @state[:addresses]["ipv4"] elsif @state[:addresses].has_key? "ipv6" @report_data[:host] = @state[:addresses]["ipv6"] end end if @state[:addresses] and @state[:addresses].has_key?("mac") @report_data[:mac] = @state[:addresses]["mac"] end if @state[:hostname] @report_data[:name] = @state[:hostname] end if @state[:uptime] @report_data[:last_boot] = @state[:uptime]["lastboot"] end if @state[:trace] and @state[:trace].has_key?(:hops) @report_data[:traceroute] = @state[:trace] end if @state[:scripts] @report_data[:scripts] = @state[:scripts] end end
collect_os_data()
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 211 def collect_os_data return unless in_tag("host") if @state[:os] @report_data[:os_fingerprint] = { :type => "host.os.nmap_fingerprint", :data => { :os_vendor => @state[:os]["vendor"], :os_family => @state[:os]["osfamily"], :os_version => @state[:os]["osgen"], :os_accuracy => @state[:os]["accuracy"].to_i } } if @state[:os].has_key? "osmatch" @report_data[:os_fingerprint][:data][:os_match] = @state[:os]["osmatch"] end end end
collect_port_data()
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 259 def collect_port_data return unless in_tag("host") if @args[:fix_services] if @state[:port]["state"] == "filtered" return end end @report_data[:ports] ||= [] port_hash = {} extra = [] @state[:port].each do |k,v| case k when "protocol" port_hash[:proto] = v when "portid" port_hash[:port] = v when "state" port_hash[:state] = determine_port_state(v) when "name" port_hash[:name] = v when "reason" port_hash[:reason] = v when "product" extra[0] = v when "version" extra[1] = v when "extrainfo" extra[2] = v when :scripts port_hash[:scripts] = v end end port_hash[:info] = extra.compact.join(" ") unless extra.empty? # Skip localhost port results when they're unknown if( port_hash[:reason] == "localhost-response" && port_hash[:state] == Msf::ServiceState::Unknown ) @report_data[:ports] else @report_data[:ports] << port_hash end end
determine_port_state(v)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 11 def determine_port_state(v) case v when "open" Msf::ServiceState::Open when "closed" Msf::ServiceState::Closed when "filtered" Msf::ServiceState::Filtered when "unknown" Msf::ServiceState::Unknown end end
end_element(name=nil)
click to toggle source
When we exit a tag, this is triggered.
# File lib/rex/parser/nmap_nokogiri.rb, line 69 def end_element(name=nil) block = @block case name when "os" collect_os_data @state[:os] = {} when "port" collect_port_data @state[:port] = {} when "host" # Roll everything up now collect_host_data host_object = report_host &block if host_object db.report_import_note(@args[:wspace],host_object) report_services(host_object,&block) report_fingerprint(host_object) report_uptime(host_object) report_traceroute(host_object) end @state.delete_if {|k| k != :current_tag} @report_data = {:wspace => @args[:wspace]} end @state[:current_tag].delete name end
record_address(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 196 def record_address(attrs) return unless in_tag("host") @state[:addresses] ||= {} address = nil type = nil attrs.each do |k,v| if k == "addr" address = v elsif k == "addrtype" type = v end end @state[:addresses][type] = address end
record_host_hop(attrs)
click to toggle source
We can certainly get fancier with self.send() magic, but leaving this pretty simple for now.
# File lib/rex/parser/nmap_nokogiri.rb, line 97 def record_host_hop(attrs) return unless in_tag("host") return unless in_tag("trace") hops = attr_hash(attrs) hops["name"] = hops.delete "host" @state[:trace][:hops] << hops end
record_host_osclass(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 126 def record_host_osclass(attrs) return unless in_tag("host") return unless in_tag("os") @state[:os] ||= {} temp_hash = attr_hash(attrs) if better_os_match(@state[:os],temp_hash) @state[:os] = temp_hash end end
record_host_osmatch(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 116 def record_host_osmatch(attrs) return unless in_tag("host") return unless in_tag("os") temp_hash = attr_hash(attrs) if temp_hash["accuracy"].to_i == 100 @state[:os] ||= {} @state[:os]["osmatch"] = temp_hash["name"] end end
record_host_script(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 143 def record_host_script(attrs) return unless in_tag("host") return if in_tag("port") temp_hash = attr_hash(attrs) if temp_hash["id"] and temp_hash["output"] @state[:scripts] ||= [] @state[:scripts] << { temp_hash["id"] => temp_hash["output"] } end end
record_host_status(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 188 def record_host_status(attrs) return unless in_tag("host") attrs.each do |k,v| next unless k == "state" @state[:host_alive] = (v == "up") end end
record_host_trace(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 105 def record_host_trace(attrs) return unless in_tag("host") @state[:trace] = attr_hash(attrs) @state[:trace][:hops] = [] end
record_host_uptime(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 111 def record_host_uptime(attrs) return unless in_tag("host") @state[:uptime] = attr_hash(attrs) end
record_hostname(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 136 def record_hostname(attrs) return unless in_tag("host") if attr_hash(attrs)["type"] == "PTR" @state[:hostname] = attr_hash(attrs)["name"] end end
record_port(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 181 def record_port(attrs) return unless in_tag("host") @state[:port] ||= {} svc = attr_hash(attrs) @state[:port] = @state[:port].merge(svc) end
record_port_script(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 154 def record_port_script(attrs) return unless in_tag("host") return unless in_tag("port") temp_hash = attr_hash(attrs) if temp_hash["id"] and temp_hash["output"] @state[:port][:scripts] ||= [] @state[:port][:scripts] << { temp_hash["id"] => temp_hash["output"] } end end
record_port_service(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 164 def record_port_service(attrs) return unless in_tag("host") return unless in_tag("port") svc = attr_hash(attrs) if svc["name"] && @args[:fix_services] svc["name"] = db.nmap_msf_service_map(svc["name"]) end @state[:port] = @state[:port].merge(svc) end
record_port_state(attrs)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 174 def record_port_state(attrs) return unless in_tag("host") return unless in_tag("port") temp_hash = attr_hash(attrs) @state[:port] = @state[:port].merge(temp_hash) end
report_fingerprint(host_object)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 327 def report_fingerprint(host_object) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:os_fingerprint] fp_note = @report_data[:os_fingerprint].merge( { :workspace => host_object.workspace, :host => host_object }) db_report(:note, fp_note) end
report_host(&block)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 338 def report_host(&block) if host_is_okay scripts = @report_data.delete(:scripts) || [] host_object = db_report(:host, @report_data.merge( :workspace => @args[:wspace] ) ) db.emit(:address,@report_data[:host],&block) if block scripts.each do |script| script.each_pair do |k,v| ntype = nse_note = { :workspace => host_object.workspace, :host => host_object, :type => "nmap.nse.#{k}.host", :data => { 'output' => v }, :update => :unique_data } db_report(:note, nse_note) end end host_object end end
report_services(host_object,&block)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 362 def report_services(host_object,&block) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:ports] return if @report_data[:ports].empty? reported = [] @report_data[:ports].each do |svc| scripts = svc.delete(:scripts) || [] svc_obj = db_report(:service, svc.merge(:host => host_object)) scripts.each do |script| script.each_pair do |k,v| ntype = nse_note = { :workspace => host_object.workspace, :host => host_object, :service => svc_obj, :type => "nmap.nse.#{k}." + (svc[:proto] || "tcp") +".#{svc[:port]}", :data => { 'output' => v }, :update => :unique_data } db_report(:note, nse_note) end end reported << svc_obj end reported end
report_traceroute(host_object)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 301 def report_traceroute(host_object) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:traceroute] tr_note = { :workspace => host_object.workspace, :host => host_object, :type => "host.nmap.traceroute", :data => { 'port' => @report_data[:traceroute]["port"].to_i, 'proto' => @report_data[:traceroute]["proto"].to_s, 'hops' => @report_data[:traceroute][:hops] } } db_report(:note, tr_note) end
report_uptime(host_object)
click to toggle source
# File lib/rex/parser/nmap_nokogiri.rb, line 315 def report_uptime(host_object) return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:last_boot] up_note = { :workspace => host_object.workspace, :host => host_object, :type => "host.last_boot", :data => { :time => @report_data[:last_boot] } } db_report(:note, up_note) end
start_element(name=nil,attrs=[])
click to toggle source
Triggered every time a new element is encountered. We keep state ourselves with the @state variable, turning things on when we get here (and turning things off when we exit in end_element
()).
# File lib/rex/parser/nmap_nokogiri.rb, line 34 def start_element(name=nil,attrs=[]) attrs = normalize_attrs(attrs) block = @block @state[:current_tag][name] = true case name when "status" record_host_status(attrs) when "address" record_address(attrs) when "osclass" record_host_osclass(attrs) when "osmatch" record_host_osmatch(attrs) when "uptime" record_host_uptime(attrs) when "hostname" record_hostname(attrs) when "port" record_port(attrs) when "state" record_port_state(attrs) when "service" record_port_service(attrs) when "script" # Not actually used in import? record_port_script(attrs) record_host_script(attrs) # Ignoring post scripts completely when "trace" record_host_trace(attrs) when "hop" record_host_hop(attrs) end end