240 lines
5.6 KiB
Ruby
240 lines
5.6 KiB
Ruby
require "rex/parser/nokogiri_doc_mixin"
|
|
|
|
module Rex
|
|
module Parser
|
|
|
|
load_nokogiri && class Outpost24Document < Nokogiri::XML::SAX::Document
|
|
|
|
include NokogiriDocMixin
|
|
|
|
def start_element(name, attrs)
|
|
@state[:current_tag][name] = true
|
|
case name
|
|
when "description", "information"
|
|
return unless in_tag("detaillist")
|
|
return unless in_tag("detail")
|
|
record_text
|
|
when "detail"
|
|
return unless in_tag("detaillist")
|
|
record_vuln
|
|
when "detaillist"
|
|
record_vulns
|
|
when "host"
|
|
return unless in_tag("hostlist")
|
|
record_host
|
|
when "hostlist"
|
|
record_hosts
|
|
when "id"
|
|
return unless in_tag("detaillist")
|
|
return unless in_tag("detail")
|
|
return unless in_tag("cve")
|
|
record_text
|
|
when "name"
|
|
return unless in_tag("hostlist") || in_tag("detaillist")
|
|
return unless in_tag("host") || in_tag("detail")
|
|
record_text
|
|
when "platform"
|
|
return unless in_tag("hostlist")
|
|
return unless in_tag("host")
|
|
record_text
|
|
when "portinfo"
|
|
return unless in_tag("portlist")
|
|
return unless in_tag("portlist-host")
|
|
record_service
|
|
when "portlist"
|
|
record_services
|
|
when "portnumber", "protocol", "service"
|
|
return unless in_tag("portlist")
|
|
return unless in_tag("portlist-host")
|
|
return unless in_tag("portinfo")
|
|
record_text
|
|
when "report", "ip"
|
|
record_text
|
|
end
|
|
end
|
|
|
|
def end_element(name)
|
|
case name
|
|
when "description", "information"
|
|
return unless in_tag("detaillist")
|
|
return unless in_tag("detail")
|
|
collect_vuln_data(name)
|
|
when "detail"
|
|
return unless in_tag("detaillist")
|
|
collect_vuln
|
|
when "detaillist"
|
|
report_vulns
|
|
when "host"
|
|
return unless in_tag("hostlist")
|
|
collect_host
|
|
when "hostlist"
|
|
report_hosts
|
|
when "id"
|
|
return unless in_tag("detaillist")
|
|
return unless in_tag("detail")
|
|
return unless in_tag("cve")
|
|
collect_vuln_data(name)
|
|
when "ip"
|
|
collect_ip
|
|
when "name"
|
|
if in_tag("hostlist") && in_tag("host")
|
|
collect_host_data(name)
|
|
elsif in_tag("detaillist") && in_tag("detail")
|
|
collect_vuln_data(name)
|
|
end
|
|
when "platform"
|
|
return unless in_tag("hostlist")
|
|
return unless in_tag("host")
|
|
collect_host_data(name)
|
|
when "portinfo"
|
|
return unless in_tag("portlist")
|
|
return unless in_tag("portlist-host")
|
|
collect_service
|
|
when "portlist"
|
|
report_services
|
|
when "portnumber", "protocol", "service"
|
|
return unless in_tag("portlist")
|
|
return unless in_tag("portlist-host")
|
|
return unless in_tag("portinfo")
|
|
collect_service_data(name)
|
|
when "report"
|
|
collect_product
|
|
end
|
|
@state[:current_tag].delete(name)
|
|
end
|
|
|
|
def record_hosts
|
|
@report_data[:hosts] = []
|
|
end
|
|
|
|
def record_services
|
|
@report_data[:services] = []
|
|
end
|
|
|
|
def record_vulns
|
|
@report_data[:vulns] = []
|
|
end
|
|
|
|
def record_host
|
|
@host = {}
|
|
end
|
|
|
|
def record_service
|
|
@service = {}
|
|
end
|
|
|
|
def record_vuln
|
|
@vuln = {}
|
|
@refs = []
|
|
end
|
|
|
|
def record_text
|
|
@state[:has_text] = true
|
|
end
|
|
|
|
def collect_host
|
|
@host[:host] = @state[:host]
|
|
@host[:name] = @state[:hname]
|
|
@host[:os_name] = @state[:os_name]
|
|
@host[:info] = @state[:pinfo]
|
|
@report_data[:hosts] << @host
|
|
end
|
|
|
|
def collect_service
|
|
@service[:host] = @state[:host]
|
|
@service[:port] = @state[:port]
|
|
@service[:proto] = @state[:proto]
|
|
@service[:name] = @state[:sname]
|
|
@service[:info] = @state[:pinfo]
|
|
@report_data[:services] << @service
|
|
end
|
|
|
|
def collect_vuln
|
|
@vuln[:host] = @state[:host]
|
|
@vuln[:name] = @state[:vname]
|
|
@vuln[:info] = @state[:vinfo]
|
|
@vuln[:refs] = @refs
|
|
@report_data[:vulns] << @vuln
|
|
end
|
|
|
|
def collect_product
|
|
@state[:has_text] = false
|
|
@state[:pinfo] = @text.strip if @text
|
|
@text = nil
|
|
end
|
|
|
|
def collect_ip
|
|
@state[:has_text] = false
|
|
@state[:host] = @text.strip if @text
|
|
@text = nil
|
|
end
|
|
|
|
def collect_host_data(name)
|
|
@state[:has_text] = false
|
|
if name == "name"
|
|
@state[:hname] = @text.strip if @text
|
|
elsif name == "platform"
|
|
if @text
|
|
@state[:os_name] = @text.strip
|
|
else
|
|
@state[:os_name] = Msf::OperatingSystems::UNKNOWN
|
|
end
|
|
end
|
|
@text = nil
|
|
end
|
|
|
|
def collect_service_data(name)
|
|
@state[:has_text] = false
|
|
if name == "portnumber"
|
|
@state[:port] = @text.strip if @text
|
|
elsif name == "protocol"
|
|
@state[:proto] = @text.strip.downcase if @text
|
|
elsif name == "service"
|
|
@state[:sname] = @text.strip if @text
|
|
end
|
|
@text = nil
|
|
end
|
|
|
|
def collect_vuln_data(name)
|
|
@state[:has_text] = false
|
|
if name == "name"
|
|
@state[:vname] = @text.strip if @text
|
|
elsif name == "description"
|
|
@state[:vinfo] = @text.strip if @text
|
|
elsif name == "information"
|
|
@state[:vinfo] << " #{@text.strip if @text}"
|
|
elsif name == "id"
|
|
@state[:ref] = @text.strip if @text
|
|
@refs << normalize_ref("CVE", @state[:ref])
|
|
end
|
|
@text = nil
|
|
end
|
|
|
|
def report_hosts
|
|
block = @block
|
|
@report_data[:hosts].each do |h|
|
|
db.emit(:address, h[:host], &block) if block
|
|
db_report(:host, h)
|
|
end
|
|
end
|
|
|
|
def report_services
|
|
block = @block
|
|
@report_data[:services].each do |s|
|
|
db.emit(:service, "#{s[:host]}:#{s[:port]}/#{s[:proto]}", &block) if block
|
|
db_report(:service, s)
|
|
end
|
|
end
|
|
|
|
def report_vulns
|
|
block = @block
|
|
@report_data[:vulns].each do |v|
|
|
db.emit(:vuln, ["#{v[:name]} (#{v[:host]})", 1], &block) if block
|
|
db_report(:vuln, v)
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|