Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/parser/nexpose_simple_document.rb
Views: 11780
# -*- coding: binary -*-1require "rex/parser/nokogiri_doc_mixin"23module Rex4module Parser56# If Nokogiri is available, define Nexpose document class.7load_nokogiri && class NexposeSimpleDocument < Nokogiri::XML::SAX::Document89include NokogiriDocMixin1011attr_reader :text1213# Triggered every time a new element is encountered. We keep state14# ourselves with the @state variable, turning things on when we15# get here (and turning things off when we exit in end_element()).16def start_element(name=nil,attrs=[])17attrs = normalize_attrs(attrs)18block = @block19@state[:current_tag][name] = true20case name21when "device"22record_device(attrs)23when "service"24record_service(attrs)25when "fingerprint"26record_service_fingerprint(attrs)27record_host_fingerprint(attrs)28when "description"29@state[:has_text] = true30record_host_fingerprint_data(name,attrs)31when "vendor", "family", "product", "version", "architecture"32@state[:has_text] = true33record_host_fingerprint_data(name,attrs)34when "vulnerability"35record_service_vuln(attrs)36record_host_vuln(attrs)37when "id"38@state[:has_text] = true39record_service_vuln_id(attrs)40record_host_vuln_id(attrs)41end42end4344# When we exit a tag, this is triggered.45def end_element(name=nil)46block = @block47case name48when "device" # Wrap it up49collect_device_data50host_object = report_host &block51report_services(host_object)52report_host_fingerprint(host_object)53report_vulns(host_object)54# Reset the state once we close a host55@state.delete_if {|k| k != :current_tag}56@report_data = {:workspace => @args[:workspace]}57when "description"58@state[:has_text] = false59collect_service_fingerprint_description60collect_host_fingerprint_data(name)61@text = nil62when "vendor", "family", "product", "version", "architecture"63@state[:has_text] = false64collect_host_fingerprint_data(name)65@text = nil66when "service"67collect_service_data68when "id"69@state[:has_text] = false70collect_service_vuln_id71collect_host_vuln_id72@text = nil73when "vulnerability"74collect_service_vuln75collect_host_vuln76@state[:references] = nil77end78@state[:current_tag].delete name79end8081def report_vulns(host_object)82vuln_count = 083block = @block84return unless host_object.kind_of? ::Mdm::Host85return unless @report_data[:vulns]86@report_data[:vulns].each do |vuln|87if vuln[:refs]88vuln[:refs] << vuln[:name]89else90vuln[:refs] = [vuln[:name]]91end92vuln[:refs].uniq!93data = {94:workspace => host_object.workspace,95:host => host_object,96:name => vuln[:name],97:info => vuln[:info],98:refs => vuln[:refs]99}100if vuln[:port] && vuln[:proto]101data[:port] = vuln[:port]102data[:proto] = vuln[:proto]103end104db_report(:vuln,data)105end106107end108109def collect_host_vuln_id110return unless in_tag("device")111return unless in_tag("vulnerability")112return if in_tag("service")113return unless @state[:host_vuln_id]114@state[:references] ||= []115ref = normalize_ref( @state[:host_vuln_id]["type"], @text )116@state[:references] << ref if ref117@state[:host_vuln_id] = nil118@text = nil119end120121def collect_service_vuln_id122return unless in_tag("device")123return unless in_tag("vulnerability")124return unless in_tag("service")125return unless @state[:service_vuln_id]126@state[:references] ||= []127ref = normalize_ref( @state[:service_vuln_id]["type"], @text )128@state[:references] << ref if ref129@state[:service_vuln_id] = nil130@text = nil131end132133def collect_service_vuln134return unless in_tag("device")135return unless in_tag("vulnerability")136return unless in_tag("service")137@report_data[:vulns] ||= []138return unless actually_vulnerable(@state[:service_vuln])139return if @state[:service]["port"].to_i == 0140vid = @state[:service_vuln]["id"].to_s.downcase141vuln = {142:name => "NEXPOSE-#{vid}",143:info => vid,144:refs => @state[:references],145:port => @state[:service]["port"].to_i,146:proto => @state[:service]["protocol"]147}148@report_data[:vulns] << vuln149end150151def collect_host_vuln152return unless in_tag("vulnerability")153return unless in_tag("device")154return if in_tag("service")155@report_data[:vulns] ||= []156return unless actually_vulnerable(@state[:host_vuln])157vid = @state[:host_vuln]["id"].to_s.downcase158vuln = {159:name => "NEXPOSE-#{vid}",160:info => vid,161:refs => @state[:references]162}163@report_data[:vulns] << vuln164end165166def record_host_vuln_id(attrs)167return unless in_tag("device")168return if in_tag("service")169@state[:host_vuln_id] = attr_hash(attrs)170end171172def record_host_vuln(attrs)173return unless in_tag("device")174return if in_tag("service")175@state[:host_vuln] = attr_hash(attrs)176end177178def record_service_vuln_id(attrs)179return unless in_tag("device")180return unless in_tag("service")181@state[:service_vuln_id] = attr_hash(attrs)182end183184def record_service_vuln(attrs)185return unless in_tag("device")186return unless in_tag("service")187@state[:service_vuln] = attr_hash(attrs)188end189190def actually_vulnerable(vuln)191vuln_result = vuln["resultCode"]192vuln_result =~ /^V[VE]$/193end194195def record_device(attrs)196attrs.each do |k,v|197next unless k == "address"198@state[:address] = v199end200end201202def record_host_fingerprint(attrs)203return unless in_tag("device")204return if in_tag("service")205@state[:host_fingerprint] = attr_hash(attrs)206end207208def collect_device_data209return unless in_tag("device")210@report_data[:host] = @state[:address]211@report_data[:state] = Msf::HostState::Alive # always212end213214def record_host_fingerprint_data(name, attrs)215return unless in_tag("device")216return if in_tag("service")217return unless in_tag("fingerprint")218@state[:host_fingerprint] ||= {}219@state[:host_fingerprint].merge! attr_hash(attrs)220end221222def collect_host_fingerprint_data(name)223return unless in_tag("device")224return if in_tag("service")225return unless in_tag("fingerprint")226return unless @text227@report_data[:host_fingerprint] ||= {}228@report_data[:host_fingerprint].merge!(@state[:host_fingerprint])229@report_data[:host_fingerprint][name] = @text.to_s.strip230@text = nil231end232233def report_host(&block)234if host_is_okay235db.emit(:address,@report_data[:host],&block) if block236host_object = db_report(:host, @report_data.merge(237:workspace => @args[:workspace] ) )238if host_object239db.report_import_note(host_object.workspace, host_object)240end241host_object242end243end244245def report_host_fingerprint(host_object)246return unless host_object.kind_of? ::Mdm::Host247return unless @report_data[:host_fingerprint].kind_of? Hash248@report_data[:host_fingerprint].reject! {|k,v| v.nil? || v.empty?}249return if @report_data[:host_fingerprint].empty?250note = {251:workspace => host_object.workspace,252:host => host_object,253:type => "host.os.nexpose_fingerprint"254}255data = {256:desc => @report_data[:host_fingerprint]["description"],257:vendor => @report_data[:host_fingerprint]["vendor"],258:family => @report_data[:host_fingerprint]["family"],259:product => @report_data[:host_fingerprint]["product"],260:version => @report_data[:host_fingerprint]["version"],261:arch => @report_data[:host_fingerprint]["architecture"]262}263db_report(:note, note.merge(:data => data))264end265266def record_service(attrs)267return unless in_tag("device")268@state[:service] = attr_hash(attrs)269end270271def record_service_fingerprint(attrs)272return unless in_tag("device")273return unless in_tag("service")274@state[:service][:fingerprint] = attr_hash(attrs)275end276277def collect_service_data278return unless in_tag("device")279port_hash = {}280@report_data[:ports] ||= []281@state[:service].each do |k,v|282case k283when "protocol"284port_hash[:proto] = v285when "port"286port_hash[:port] = v287when "name"288sname = v.to_s.downcase.split("(")[0].strip289if sname == "<unknown>"290port_hash[:name] = nil291else292port_hash[:name] = db.nmap_msf_service_map(sname)293end294end295end296if @state[:service_fingerprint]297port_hash[:info] = "#{@state[:service_fingerprint]}"298end299@report_data[:ports] << port_hash.clone300@state.delete :service_fingerprint301@state.delete :service302@report_data[:ports]303end304305def collect_service_fingerprint_description306return unless in_tag("device")307return unless in_tag("service")308return unless in_tag("fingerprint")309return unless @text310@state[:service_fingerprint] = @text.to_s.strip311@text = nil312end313314def report_services(host_object)315return unless host_object.kind_of? ::Mdm::Host316return unless @report_data[:ports]317return if @report_data[:ports].empty?318reported = []319@report_data[:ports].each do |svc|320reported << db_report(:service, svc.merge(:host => host_object))321end322reported323end324325end326327end328end329330331332