Merge in nCircle support from Dave Lassalle, handle file reads more consistently
git-svn-id: file:///home/svn/framework3/trunk@10902 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
13a93d41f6
commit
652764ebd3
|
@ -3,6 +3,8 @@ require 'rex/parser/nexpose_xml'
|
||||||
require 'rex/parser/retina_xml'
|
require 'rex/parser/retina_xml'
|
||||||
require 'rex/parser/netsparker_xml'
|
require 'rex/parser/netsparker_xml'
|
||||||
require 'rex/parser/nessus_xml'
|
require 'rex/parser/nessus_xml'
|
||||||
|
require 'rex/parser/ip360_xml'
|
||||||
|
require 'rex/parser/ip360_aspl_xml'
|
||||||
require 'rex/socket'
|
require 'rex/socket'
|
||||||
require 'zip'
|
require 'zip'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
|
@ -1883,8 +1885,11 @@ class DBManager
|
||||||
@import_filedata = {}
|
@import_filedata = {}
|
||||||
@import_filedata[:filename] = filename
|
@import_filedata[:filename] = filename
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
|
|
||||||
if data[0,4] == "PK\x03\x04"
|
if data[0,4] == "PK\x03\x04"
|
||||||
data = Zip::ZipFile.open(filename)
|
data = Zip::ZipFile.open(filename)
|
||||||
end
|
end
|
||||||
|
@ -1976,6 +1981,9 @@ class DBManager
|
||||||
when /netsparker/
|
when /netsparker/
|
||||||
@import_filedata[:type] = "NetSparker XML"
|
@import_filedata[:type] = "NetSparker XML"
|
||||||
return :netsparker_xml
|
return :netsparker_xml
|
||||||
|
when /audits/
|
||||||
|
@import_filedata[:type] = "IP360 XML v3"
|
||||||
|
return :ip360_xml_v3
|
||||||
else
|
else
|
||||||
# Give up if we haven't hit the root tag in the first few lines
|
# Give up if we haven't hit the root tag in the first few lines
|
||||||
break if line_count > 10
|
break if line_count > 10
|
||||||
|
@ -2131,8 +2139,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_nexpose_simplexml(args.merge(:data => data))
|
import_nexpose_simplexml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2141,8 +2151,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_msf_xml(args.merge(:data => data))
|
import_msf_xml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2707,8 +2719,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_nexpose_rawxml(args.merge(:data => data))
|
import_nexpose_rawxml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2880,8 +2894,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_retina_xml(args.merge(:data => data))
|
import_retina_xml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2962,8 +2978,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_netsparker_xml(args.merge(:data => data))
|
import_netsparker_xml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3345,8 +3363,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_nmap_xml(args.merge(:data => data))
|
import_nmap_xml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3499,8 +3519,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_nessus_nbe(args.merge(:data => data))
|
import_nessus_nbe(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3582,6 +3604,20 @@ class DBManager
|
||||||
raise DBImportError.new("No OpenVAS XML support. Please submit a patch to msfdev[at]metasploit.com")
|
raise DBImportError.new("No OpenVAS XML support. Please submit a patch to msfdev[at]metasploit.com")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Import IP360 XML v3 output
|
||||||
|
#
|
||||||
|
def import_ip360_xml_file(args={})
|
||||||
|
filename = args[:filename]
|
||||||
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
|
data = ""
|
||||||
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
|
import_ip360_xml_v3(args.merge(:data => data))
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Import Nessus XML v1 and v2 output
|
# Import Nessus XML v1 and v2 output
|
||||||
#
|
#
|
||||||
|
@ -3591,8 +3627,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
|
|
||||||
if data.index("NessusClientData_v2")
|
if data.index("NessusClientData_v2")
|
||||||
import_nessus_xml_v2(args.merge(:data => data))
|
import_nessus_xml_v2(args.merge(:data => data))
|
||||||
|
@ -3757,6 +3795,125 @@ class DBManager
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Import IP360's xml output
|
||||||
|
#
|
||||||
|
def import_ip360_xml_v3(args={}, &block)
|
||||||
|
data = args[:data]
|
||||||
|
wspace = args[:wspace] || workspace
|
||||||
|
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||||
|
|
||||||
|
# @aspl = {'vulns' => {'name' => { }, 'cve' => { }, 'bid' => { } }
|
||||||
|
# 'oses' => {'name' } }
|
||||||
|
|
||||||
|
aspl_path = File.join(Msf::Config.data_directory, "data", "ncircle", "ip360.aspl")
|
||||||
|
|
||||||
|
if not ::File.exist?(aspl_path)
|
||||||
|
raise DBImportError.new("The nCircle IP360 ASPL file is not present.\n Download ASPL from nCircle VNE | Administer | Support | Resources, unzip it, and save it as " + aspl_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ::File.readable?(aspl_path)
|
||||||
|
raise DBImportError.new("Could not read the IP360 ASPL XML file provided at " + aspl_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
# parse nCircle ASPL file
|
||||||
|
aspl = ""
|
||||||
|
::File.open(aspl_path, "rb") do |f|
|
||||||
|
aspl = f.read(f.stat.size)
|
||||||
|
end
|
||||||
|
|
||||||
|
@asplhash = nil
|
||||||
|
parser = Rex::Parser::IP360ASPLXMLStreamParser.new
|
||||||
|
parser.on_found_aspl = Proc.new { |asplh|
|
||||||
|
@asplhash = asplh
|
||||||
|
}
|
||||||
|
REXML::Document.parse_stream(aspl, parser)
|
||||||
|
|
||||||
|
#@host = {'hname' => nil, 'addr' => nil, 'mac' => nil, 'os' => nil, 'hid' => nil,
|
||||||
|
# 'vulns' => ['vuln' => {'vulnid' => nil, 'port' => nil, 'proto' => nil } ],
|
||||||
|
# 'apps' => ['app' => {'appid' => nil, 'svcid' => nil, 'port' => nil, 'proto' => nil } ],
|
||||||
|
# 'shares' => []
|
||||||
|
# }
|
||||||
|
|
||||||
|
# nCircle has some quotes escaped which causes the parser to break
|
||||||
|
# we don't need these lines so just replace \" with "
|
||||||
|
data.gsub!(/\\"/,'"')
|
||||||
|
|
||||||
|
# parse nCircle Scan Output
|
||||||
|
parser = Rex::Parser::IP360XMLStreamParser.new
|
||||||
|
parser.on_found_host = Proc.new { |host|
|
||||||
|
|
||||||
|
addr = host['addr'] || host['hname']
|
||||||
|
|
||||||
|
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
|
||||||
|
|
||||||
|
if bl.include? addr
|
||||||
|
next
|
||||||
|
else
|
||||||
|
yield(:address,addr) if block
|
||||||
|
end
|
||||||
|
|
||||||
|
os = host['os']
|
||||||
|
yield(:os, os) if block
|
||||||
|
if os
|
||||||
|
report_note(
|
||||||
|
:workspace => wspace,
|
||||||
|
:host => addr,
|
||||||
|
:type => 'host.os.ip360_fingerprint',
|
||||||
|
:data => {
|
||||||
|
:os => @asplhash['oses'][os].to_s.strip
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
hname = host['hname']
|
||||||
|
|
||||||
|
if hname
|
||||||
|
report_host(
|
||||||
|
:workspace => wspace,
|
||||||
|
:host => addr,
|
||||||
|
:name => hname.to_s.strip
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
mac = host['mac']
|
||||||
|
|
||||||
|
if mac
|
||||||
|
report_host(
|
||||||
|
:workspace => wspace,
|
||||||
|
:host => addr,
|
||||||
|
:mac => mac.to_s.strip.upcase
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
host['apps'].each do |item|
|
||||||
|
port = item['port'].to_s
|
||||||
|
proto = item['proto'].to_s
|
||||||
|
|
||||||
|
handle_ip360_v3_svc(wspace, addr, port, proto, hname)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
host['vulns'].each do |item|
|
||||||
|
vulnid = item['vulnid'].to_s
|
||||||
|
port = item['port'].to_s
|
||||||
|
proto = item['proto'] || "tcp"
|
||||||
|
vulnname = @asplhash['vulns']['name'][vulnid]
|
||||||
|
cves = @asplhash['vulns']['cve'][vulnid]
|
||||||
|
bids = @asplhash['vulns']['bid'][vulnid]
|
||||||
|
|
||||||
|
yield(:port, port) if block
|
||||||
|
|
||||||
|
handle_ip360_v3_vuln(wspace, addr, port, proto, hname, vulnid, vulnname, cves, bids)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
yield(:end, hname) if block
|
||||||
|
}
|
||||||
|
|
||||||
|
REXML::Document.parse_stream(data, parser)
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Import Qualys' xml output
|
# Import Qualys' xml output
|
||||||
#
|
#
|
||||||
|
@ -3764,8 +3921,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_qualys_xml(args.merge(:data => data))
|
import_qualys_xml(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3852,8 +4011,10 @@ class DBManager
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
|
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
import_ip_list(args.merge(:data => data))
|
import_ip_list(args.merge(:data => data))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3876,8 +4037,11 @@ class DBManager
|
||||||
def import_amap_log_file(args={})
|
def import_amap_log_file(args={})
|
||||||
filename = args[:filename]
|
filename = args[:filename]
|
||||||
wspace = args[:wspace] || workspace
|
wspace = args[:wspace] || workspace
|
||||||
f = File.open(filename, 'rb')
|
data = ""
|
||||||
data = f.read(f.stat.size)
|
::File.open(filename, 'rb') do |f|
|
||||||
|
data = f.read(f.stat.size)
|
||||||
|
end
|
||||||
|
|
||||||
case import_filetype_detect(data)
|
case import_filetype_detect(data)
|
||||||
when :amap_log
|
when :amap_log
|
||||||
import_amap_log(args.merge(:data => data))
|
import_amap_log(args.merge(:data => data))
|
||||||
|
@ -4101,6 +4265,65 @@ protected
|
||||||
report_vuln(vuln)
|
report_vuln(vuln)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# IP360 v3 vuln
|
||||||
|
#
|
||||||
|
def handle_ip360_v3_svc(wspace,addr,port,proto,hname)
|
||||||
|
|
||||||
|
report_host(:workspace => wspace, :host => addr, :state => Msf::HostState::Alive)
|
||||||
|
|
||||||
|
info = { :workspace => wspace, :host => addr, :port => port, :proto => proto }
|
||||||
|
if hname != "unknown" and hname[-1,1] != "?"
|
||||||
|
info[:name] = hname
|
||||||
|
end
|
||||||
|
|
||||||
|
if port.to_i != 0
|
||||||
|
report_service(info)
|
||||||
|
end
|
||||||
|
end #handle_ip360_v3_svc
|
||||||
|
|
||||||
|
#
|
||||||
|
# IP360 v3 vuln
|
||||||
|
#
|
||||||
|
def handle_ip360_v3_vuln(wspace,addr,port,proto,hname,vulnid,vulnname,cves,bids)
|
||||||
|
|
||||||
|
report_host(:workspace => wspace, :host => addr, :state => Msf::HostState::Alive)
|
||||||
|
|
||||||
|
info = { :workspace => wspace, :host => addr, :port => port, :proto => proto }
|
||||||
|
if hname != "unknown" and hname[-1,1] != "?"
|
||||||
|
info[:name] = hname
|
||||||
|
end
|
||||||
|
|
||||||
|
if port.to_i != 0
|
||||||
|
report_service(info)
|
||||||
|
end
|
||||||
|
|
||||||
|
refs = []
|
||||||
|
|
||||||
|
cves.split(/,/).each do |cve|
|
||||||
|
refs.push(cve.to_s)
|
||||||
|
end if cves
|
||||||
|
|
||||||
|
bids.split(/,/).each do |bid|
|
||||||
|
refs.push('BID-' + bid.to_s)
|
||||||
|
end if bids
|
||||||
|
|
||||||
|
description = nil # not working yet
|
||||||
|
vuln = {
|
||||||
|
:workspace => wspace,
|
||||||
|
:host => addr,
|
||||||
|
:name => vulnname,
|
||||||
|
:info => description ? description : "",
|
||||||
|
:refs => refs
|
||||||
|
}
|
||||||
|
|
||||||
|
if port.to_i != 0
|
||||||
|
vuln[:port] = port
|
||||||
|
vuln[:proto] = proto
|
||||||
|
end
|
||||||
|
|
||||||
|
report_vuln(vuln)
|
||||||
|
end #handle_ip360_v3_vuln
|
||||||
|
|
||||||
#
|
#
|
||||||
# Qualys report parsing/handling
|
# Qualys report parsing/handling
|
||||||
|
|
|
@ -69,6 +69,7 @@ class Db
|
||||||
"db_import_amap_log" => "Import a THC-Amap scan results file (-o )",
|
"db_import_amap_log" => "Import a THC-Amap scan results file (-o )",
|
||||||
"db_import_nessus_nbe" => "Import a Nessus scan result file (NBE)",
|
"db_import_nessus_nbe" => "Import a Nessus scan result file (NBE)",
|
||||||
"db_import_nessus_xml" => "Import a Nessus scan result file (NESSUS)",
|
"db_import_nessus_xml" => "Import a Nessus scan result file (NESSUS)",
|
||||||
|
"db_import_ip360_xml" => "Import an IP360 scan result file (XML)",
|
||||||
"db_import_nmap_xml" => "Import a Nmap scan results file (-oX)",
|
"db_import_nmap_xml" => "Import a Nmap scan results file (-oX)",
|
||||||
"db_import_qualys_xml" => "Import a Qualys scan results file (XML)",
|
"db_import_qualys_xml" => "Import a Qualys scan results file (XML)",
|
||||||
"db_import_msfe_xml" => "Import a Metasploit Express report (XML)",
|
"db_import_msfe_xml" => "Import a Metasploit Express report (XML)",
|
||||||
|
@ -1236,6 +1237,26 @@ class Db
|
||||||
framework.db.import_nessus_xml_file(:filename => args[0])
|
framework.db.import_nessus_xml_file(:filename => args[0])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Import IP360 XML files
|
||||||
|
#
|
||||||
|
def cmd_db_import_ip360_xml(*args)
|
||||||
|
return unless active?
|
||||||
|
if (not (args and args.length == 1))
|
||||||
|
print_status("Usage: db_import_ip360_xml <ip360.xml>")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
warn_about_db_import(args[0])
|
||||||
|
|
||||||
|
if (not File.readable?(args[0]))
|
||||||
|
print_status("Could not read the IP360 Scan file provided")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
framework.db.import_ip360_xml_file(:filename => args[0])
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Import Nmap data from a file
|
# Import Nmap data from a file
|
||||||
#
|
#
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
require 'rexml/document'
|
||||||
|
require 'rex/ui'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Parser
|
||||||
|
|
||||||
|
|
||||||
|
class IP360ASPLXMLStreamParser
|
||||||
|
|
||||||
|
@vulnid = nil
|
||||||
|
@appid = nil
|
||||||
|
@location = nil
|
||||||
|
|
||||||
|
attr_accessor :on_found_aspl
|
||||||
|
|
||||||
|
def initialize(&block)
|
||||||
|
reset_state
|
||||||
|
on_found_aspl = block if block
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_state
|
||||||
|
@aspl = {'vulns' => {'name' => { }, 'cve' => { }, 'bid' => { } },
|
||||||
|
'oses' => {'name' => { } } }
|
||||||
|
@state = :generic_state
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_start(name, attributes)
|
||||||
|
case name
|
||||||
|
when "vulns"
|
||||||
|
@location = "vulns"
|
||||||
|
when "vuln"
|
||||||
|
@vulnid = attributes['id'].strip
|
||||||
|
when "name"
|
||||||
|
@state = :is_name
|
||||||
|
when "advisories"
|
||||||
|
@c = ""
|
||||||
|
@cfirst = 1
|
||||||
|
@b = ""
|
||||||
|
@bfirst = 1
|
||||||
|
@x = Hash.new
|
||||||
|
when "publisher"
|
||||||
|
@state = :is_pub
|
||||||
|
when "id"
|
||||||
|
@state = :is_refid
|
||||||
|
when "operatingSystems"
|
||||||
|
@location = "os"
|
||||||
|
when "operatingSystem"
|
||||||
|
@osid = attributes['id'].strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def text(str)
|
||||||
|
case @state
|
||||||
|
when :is_name
|
||||||
|
@aspl['vulns']['name'][@vulnid] = str if @location == "vulns"
|
||||||
|
@aspl['oses'][@osid] = str if @location == "os"
|
||||||
|
when :is_pub
|
||||||
|
@x['pub'] = str
|
||||||
|
when :is_refid
|
||||||
|
@x['refid'] = str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_end(name)
|
||||||
|
case name
|
||||||
|
when "ontology"
|
||||||
|
on_found_aspl.call(@aspl) if on_found_aspl
|
||||||
|
reset_state
|
||||||
|
when "advisory"
|
||||||
|
if (@x['pub'] =~ /CVE/)
|
||||||
|
if (@cfirst == 0)
|
||||||
|
@c += ","
|
||||||
|
end
|
||||||
|
@c += @x['refid']
|
||||||
|
@cfirst = 0
|
||||||
|
elsif (@x['pub'] =~ /BugTraq/)
|
||||||
|
if (@bfirst == 0)
|
||||||
|
@b += ","
|
||||||
|
end
|
||||||
|
@b += @x['refid']
|
||||||
|
@bfirst = 0
|
||||||
|
end
|
||||||
|
when "advisories"
|
||||||
|
@aspl['vulns']['cve'][@vulnid] = @c
|
||||||
|
@aspl['vulns']['bid'][@vulnid] = @b
|
||||||
|
@c = ""
|
||||||
|
@b = ""
|
||||||
|
end
|
||||||
|
@state = :generic_state
|
||||||
|
end
|
||||||
|
|
||||||
|
# We don't need these methods, but they're necessary to keep REXML happy
|
||||||
|
#
|
||||||
|
def xmldecl(version, encoding, standalone); end
|
||||||
|
def cdata; end
|
||||||
|
def comment(str); end
|
||||||
|
def instruction(name, instruction); end
|
||||||
|
def attlist; end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,93 @@
|
||||||
|
require 'rexml/document'
|
||||||
|
require 'rex/ui'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Parser
|
||||||
|
|
||||||
|
|
||||||
|
class IP360XMLStreamParser
|
||||||
|
|
||||||
|
attr_accessor :on_found_host
|
||||||
|
|
||||||
|
def initialize(&block)
|
||||||
|
reset_state
|
||||||
|
on_found_host = block if block
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset_state
|
||||||
|
@host = {'hname' => nil, 'hid' => nil, 'addr' => nil, 'mac' => nil, 'os' => nil,
|
||||||
|
'vulns' => ['vuln' => {'vulnid' => nil, 'port' => nil, 'proto' => nil} ],
|
||||||
|
'apps' => ['app' => {'appid' => nil, 'svcid' => nil, 'port' => nil, 'proto' => nil } ],
|
||||||
|
}
|
||||||
|
@state = :generic_state
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_start(name, attributes)
|
||||||
|
case name
|
||||||
|
when "host"
|
||||||
|
@host['hid'] = attributes['persistent_id']
|
||||||
|
when "ip"
|
||||||
|
@state = :is_ip
|
||||||
|
when "dnsName"
|
||||||
|
@state = :is_fqdn
|
||||||
|
when "macAddress"
|
||||||
|
@state = :is_mac
|
||||||
|
when "os"
|
||||||
|
@host['os'] = attributes['id']
|
||||||
|
when "vulnerability"
|
||||||
|
@x = Hash.new
|
||||||
|
@x['vulnid'] = attributes['id']
|
||||||
|
when "port"
|
||||||
|
@state = :is_port
|
||||||
|
when "protocol"
|
||||||
|
@state = :is_proto
|
||||||
|
when "application"
|
||||||
|
@y = Hash.new
|
||||||
|
@y['appid'] = attributes['application_id']
|
||||||
|
@y['svcid'] = attributes['svcid']
|
||||||
|
@y['port'] = attributes['port']
|
||||||
|
@y['proto'] = attributes['protocol']
|
||||||
|
@host['apps'].push @y
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def text(str)
|
||||||
|
case @state
|
||||||
|
when :is_fqdn
|
||||||
|
@host['hname'] = str
|
||||||
|
when :is_ip
|
||||||
|
@host['addr'] = str
|
||||||
|
when :is_mac
|
||||||
|
@host['mac'] = str
|
||||||
|
when :is_port
|
||||||
|
@x['port'] = str
|
||||||
|
when :is_proto
|
||||||
|
@x['proto'] = str
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_end(name)
|
||||||
|
case name
|
||||||
|
when "host"
|
||||||
|
on_found_host.call(@host) if on_found_host
|
||||||
|
reset_state
|
||||||
|
when "vulnerability"
|
||||||
|
@host['vulns'].push @x
|
||||||
|
end
|
||||||
|
@state = :generic_state
|
||||||
|
end
|
||||||
|
|
||||||
|
def cdata(d)
|
||||||
|
#do nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
# We don't need these methods, but they're necessary to keep REXML happy
|
||||||
|
#
|
||||||
|
def xmldecl(version, encoding, standalone); end
|
||||||
|
def comment(str); end
|
||||||
|
def instruction(name, instruction); end
|
||||||
|
def attlist; end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue