metasploit-framework/lib/rex/parser/outpost24_nokogiri.rb

241 lines
5.6 KiB
Ruby

# -*- coding: binary -*-
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