class Rex::Parser::FoundstoneDocument
Public Instance Methods
check_for_correct_report_type(attrs,&block)
click to toggle source
Nothing technically stopping us from parsing this as well, but saving this for later
# File lib/rex/parser/foundstone_nokogiri.rb, line 83 def check_for_correct_report_type(attrs,&block) report_type = attr_hash(attrs)["ReportType"] if report_type == "Network Inventory" @report_type_ok = true else if report_type == "Risk Data" msg = "The Foundstone/Mcafee report type '#{report_type}' is not currently supported" msg << ",\nso no data will be imported. Please use the 'Network Inventory' report instead." else msg = ".\nThe Foundstone/Macafee report type '#{report_type}' is unsupported." end db.emit(:warning,msg,&block) if block @report_type_ok = false end end
collect_cve()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 108 def collect_cve return unless in_tag("VulnsFound") return unless in_tag("HostData") return unless in_tag("Host") cve = @text.to_s @state[:vuln][:cves] ||= [] @state[:vuln][:cves] << cve unless cve == "CVE-MAP-NOMATCH" @text = nil end
collect_host_data()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 201 def collect_host_data @report_data[:host] = @state[:host]["IPAddress"] if @state[:host]["NBName"] && !@state[:host]["NBName"].empty? @report_data[:name] = @state[:host]["NBName"] elsif @state[:host]["DNSName"] && !@state[:host]["DNSName"].empty? @report_data[:name] = @state[:host]["DNSName"] end if @state[:host]["OSName"] && !@state[:host]["OSName"].empty? @report_data[:os_fingerprint] = @state[:host]["OSName"] end @report_data[:state] = Msf::HostState::Alive @report_data[:mac] = @state[:mac] if @state[:mac] end
collect_port()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 153 def collect_port return unless in_tag("Service") return unless in_tag("ServicesFound") return unless in_tag("Host") return if @text.nil? || @text.empty? @state[:service][:port] = @text.strip @text = nil end
collect_protocol()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 162 def collect_protocol return unless in_tag("Service") return unless in_tag("ServicesFound") return unless in_tag("Host") return if @text.nil? || @text.empty? @state[:service][:proto] = @text.strip @text = nil end
collect_risk()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 99 def collect_risk return unless in_tag("VulnsFound") return unless in_tag("HostData") return unless in_tag("Host") risk = @text.to_s.to_i @state[:vuln][:risk] = risk @text = nil end
collect_service()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 183 def collect_service return unless in_tag("ServicesFound") return unless in_tag("Host") return unless @state[:service][:port] @report_data[:ports] ||= [] port_hash = {} port_hash[:port] = @state[:service][:port] port_hash[:proto] = @state[:service][:proto] port_hash[:info] = @state[:service][:banner] port_hash[:name] = db.nmap_msf_service_map(@state[:service]["ServiceName"]) @report_data[:ports] << port_hash end
collect_vuln()
click to toggle source
Determines if we should keep the vuln or not. Note that we cannot tie them to a service.
# File lib/rex/parser/foundstone_nokogiri.rb, line 120 def collect_vuln return unless in_tag("VulnsFound") return unless in_tag("HostData") return unless in_tag("Host") return if @state[:vuln][:risk] == 0 @report_data[:vulns] ||= [] vuln_hash = {} vuln_hash[:name] = @state[:vuln]["VulnName"] refs = [] refs << "FID-#{@state[:vuln]["id"]}" if @state[:vuln][:cves] @state[:vuln][:cves].each {|cve| refs << cve} end vuln_hash[:refs] = refs @report_data[:vulns] << vuln_hash end
end_element(name=nil)
click to toggle source
When we exit a tag, this is triggered.
# File lib/rex/parser/foundstone_nokogiri.rb, line 42 def end_element(name=nil) block = @block return unless @report_type_ok case name when "Host" # Wrap it up collect_host_data host_object = report_host &block if host_object db.report_import_note(@args[:wspace],host_object) report_fingerprint(host_object) report_services(host_object) report_vulns(host_object) end # Reset the state once we close a host @state.delete_if {|k| k != :current_tag} @report_data = {:wspace => args[:wspace]} when "Port" @state[:has_text] = false collect_port when "Protocol" @state[:has_text] = false collect_protocol when "Banner" collect_banner @state[:has_text] = false when "Service" collect_service when "Vuln" collect_vuln when "Risk" @state[:has_text] = false collect_risk when "CVE" @state[:has_text] = false collect_cve end @state[:current_tag].delete name end
first_line(str)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 288 def first_line(str) str.split("\n").first.to_s.strip end
first_line_only?(service)
click to toggle source
Services
where we only care about the first line of the banner tag.
# File lib/rex/parser/foundstone_nokogiri.rb, line 271 def first_line_only?(service) svcs = %w{ vnc ftp ftps smtp oracle-tns nntp ssh ntp } 9.times {|i| svcs << "vnc-#{i}"} svcs.include? service end
needs_more_processing?(service)
click to toggle source
Services
where we need to do more processing before handing the banner back.
# File lib/rex/parser/foundstone_nokogiri.rb, line 281 def needs_more_processing?(service) svcs = %w{ microsoft-ds loc-srv http https sunrpc netbios-ns } svcs.include? service end
process_service(service,banner)
click to toggle source
XXX: Actually implement more of these
# File lib/rex/parser/foundstone_nokogiri.rb, line 293 def process_service(service,banner) meth = "process_service_#{service.gsub("-","_")}" if self.respond_to? meth self.send meth, banner else return (first_line banner) end end
process_service_http(banner)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 323 def process_service_http(banner) server = nil banner.each_line do |line| if line =~ /^Server:\s+(.*)/ server = $1 break end end server || first_line(banner) end
Also aliased as: process_service_https, process_service_rtsp
process_service_microsoft_ds(banner)
click to toggle source
XXX: Make this behave more like the smb scanner
# File lib/rex/parser/foundstone_nokogiri.rb, line 311 def process_service_microsoft_ds(banner) lm_regex = /Native LAN Manager/ lm_banner = nil banner.each_line { |line| if line[lm_regex] lm_banner = line break end } lm_banner || first_line(banner) end
process_service_netbios_ns(banner)
click to toggle source
XXX: Register a proper netbios note as the regular scanner does.
# File lib/rex/parser/foundstone_nokogiri.rb, line 304 def process_service_netbios_ns(banner) mac_regex = /[0-9A-Fa-f:]{17}/ @state[:mac] = banner[mac_regex] first_line banner end
record_host(attrs)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 196 def record_host(attrs) return unless in_tag("HostData") @state[:host] = attr_hash(attrs) end
record_service(attrs)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 147 def record_service(attrs) return unless in_tag("ServicesFound") return unless in_tag("Host") @state[:service] = attr_hash(attrs) end
record_vuln(attrs)
click to toggle source
These are per host.
# File lib/rex/parser/foundstone_nokogiri.rb, line 138 def record_vuln(attrs) return unless in_tag("VulnsFound") return unless in_tag("HostData") return unless in_tag("Host") @state[:vulns] ||= [] @state[:vuln] = attr_hash(attrs) # id and VulnName end
report_fingerprint(host_object)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 224 def report_fingerprint(host_object) fp_note = { :workspace => host_object.workspace, :host => host_object, :type => 'host.os.foundstone_fingerprint', :data => {:os => @report_data[:os_fingerprint] } } db_report(:note, fp_note) end
report_host(&block)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 215 def report_host(&block) return unless in_tag("HostData") if host_is_okay db.emit(:address,@report_data[:host],&block) if block host_info = @report_data.merge(:workspace => @args[:wspace]) db_report(:host,host_info) end end
report_services(host_object)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 234 def report_services(host_object) return unless in_tag("HostData") return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:ports] return if @report_data[:ports].empty? @report_data[:ports].each do |svc| db_report(:service, svc.merge(:host => host_object)) end end
report_vulns(host_object)
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 244 def report_vulns(host_object) return unless in_tag("HostData") return unless host_object.kind_of? ::Mdm::Host return unless @report_data[:vulns] return if @report_data[:vulns].empty? @report_data[:vulns].each do |vuln| db_report(:vuln, vuln.merge(:host => host_object)) end end
start_document()
click to toggle source
# File lib/rex/parser/foundstone_nokogiri.rb, line 11 def start_document @report_type_ok = true # Optimistic 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/foundstone_nokogiri.rb, line 18 def start_element(name=nil,attrs=[]) attrs = normalize_attrs(attrs) block = @block return unless @report_type_ok @state[:current_tag][name] = true case name when "ReportInfo" check_for_correct_report_type(attrs,&block) when "Host" record_host(attrs) when "Service" record_service(attrs) when "Port", "Protocol", "Banner" @state[:has_text] = true when "Vuln" # under VulnsFound, ignore risk 0 things record_vuln(attrs) when "Risk" # for Vuln @state[:has_text] = true when "CVE" # Under Vuln @state[:has_text] = true end end