2017-07-27 5 views
1

Ich versuche, einige nmap XML zu analysieren, um verschiedene Werte über Nokogiri abzurufen, aber eine Weile Zeit haben, Rekursion herauszufinden. Was ich will, ist das ip_address und jedes port Element, das ein untergeordnetes Element von status='open' hat. Ich möchte in der Lage sein, jede Gruppe in ein JSON-Objekt in eine Datenbank-Spalte für eine spätere Anzeige zu speichern:Abrufen geschachtelter Ergebnisse mit Nokogiri

Bisher ist hier mein Code:

require 'nokogiri' 
require 'json' 

doc = File.open("network_ports.xml") { |f| Nokogiri::XML(f) } 

doc.xpath('//host').each do |host| 
    @ip_address = host.at_xpath("address[@addrtype='ipv4']").at_xpath("@addr").value 
    puts "Found Host: #{@ip_address}" 
    host.xpath('ports/port').each do |port|  
    if port.at_xpath("state[@state='open']") 
     puts port.at_xpath("port[@portid]").value 
    end 
    end 
end 

jedoch meine Ausgabe mit der jetzt gebrochen folgende Fehlermeldung:

port_parser.rb:11:in `block (2 levels) in <main>': undefined method `value' for nil:NilClass (NoMethodError) 

Einige gleichen Eingang aus der Datei:

<host starttime="1501187906" endtime="1501189103"><status state="up" reason="syn-ack" reason_ttl="0"/> 
<address addr="10.10.10.1" addrtype="ipv4"/> 
<hostnames> 
<hostname name="eclipse" type="PTR"/> 
</hostnames> 
<ports><extraports state="closed" count="996"> 
<extrareasons reason="conn-refused" count="996"/> 
</extraports> 
<port protocol="tcp" portid="53"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="domain" product="dnsmasq" version="2.45" method="probed" conf="10"><cpe>cpe:/a:thekelleys:dnsmasq:2.45</cpe></service></port> 
<port protocol="tcp" portid="80"><state state="filtered" reason="syn-ack" reason_ttl="0"/><service name="http" product="DD-WRT milli_httpd" hostname="eclipse" method="probed" conf="10"/></port> 
<port protocol="tcp" portid="443"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="https" tunnel="ssl" method="table" conf="3"/></port> 
<port protocol="tcp" portid="2222"><state state="open" reason="syn-ack" reason_ttl="0"/><service name="ssh" product="Dropbear sshd" version="0.52" extrainfo="protocol 2.0" ostype="Linux" method="probed" conf="10"><cpe>cpe:/a:matt_johnston:dropbear_ssh_server:0.52</cpe><cpe>cpe:/o:linux:linux_kernel</cpe></service></port> 
</ports> 
<times srtt="4727" rttvar="1840" to="100000"/> 
</host> 

Bin ich auf ein Problem gestoßen, weil ich von dem verschachtelten state Element innerhalb des port Elements abhängig bin, das ich in der Lage sein muss, den portid Attributwert aus zu bekommen?

Am Ende hoffe ich nur für einige Ausgabe wie:

Found host: 10.10.10.1 
    port 22/tcp open 
    port 23/tcp open 
Found host: 10.10.10.2 
    port 443/tcp open 
    port 5432/tcp open 
etc... 

Wenn Sie den Code auf Reinigung Vorschläge haben, ich bin ganz und Ohren!

Antwort

1

Alles mit Ihrem Code scheint zu funktionieren gut, mit Ausnahme von

puts port.at_xpath("port[@portid]").value 

sind Sie bereits am port Elemente, so brauchen Sie nur die XPath @portid

puts port.at_xpath("@portid").value 

und mit Ihrem Beispiel network_ports.xml, das

# Found Host: 10.10.10.1 
# 53 
# 443 
# 2222 
ausgibt 0
+0

Ah, das ist mein Problem! Die Regression vom Kind-Zustand-Element war also überhaupt kein Problem! Vielen Dank – Godzilla74

0

Kennen Sie die NMAP gem?

require 'nmap/xml' 

Nmap::XML.new('scan.xml') do |xml| 
    xml.each_host do |host| 
    puts "[#{host.ip}]" 

    host.each_port do |port| 
     puts " #{port.number}/#{port.protocol}\t#{port.state}\t#{port.service}" 
    end 
    end 
end