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/ci_document.rb
Views: 11779
# -*- coding: binary -*-1require "rex/parser/nokogiri_doc_mixin"234module Rex5module Parser67# If Nokogiri is available, define the document class.8load_nokogiri && class CIDocument < Nokogiri::XML::SAX::Document910include NokogiriDocMixin1112attr_reader :text1314def initialize(*args)15super(*args)16@state[:has_text] = true17end1819# Triggered every time a new element is encountered. We keep state20# ourselves with the @state variable, turning things on when we21# get here (and turning things off when we exit in end_element()).22def start_element(name=nil,attrs=[])23attrs = normalize_attrs(attrs)24block = @block2526r = { :e => name }27attrs.each { |pair| r[pair[0]] = pair[1] }2829if @state[:path]30@state[:path].push r31end3233case name34when "entity"35@state[:path] = [ r ]36record_device(r)37when "property"38return if not @state[:address]39return if not @state[:props]40@state[:props] << [ r["type"], r["key"]]41end42end4344# When we exit a tag, this is triggered.45def end_element(name=nil)46block = @block47case name48when "entity" # Wrap it up49if @state[:address]50host_object = report_host &block51report_services(host_object)52report_vulns(host_object)53end54# Reset the state once we close a host55@report_data = {:workspace => @args[:workspace]}56@state[:root] = {}57when "property"58if @state[:props]59@text.strip! if @text60process_property61@state[:props].pop62end63end64@state[:path].pop65@text = nil66end6768def record_device(info)69if info["class"] and info["class"] == "host" and info["name"]70address = info["name"].to_s.gsub(/^.*\//, '')71return if address !~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/72@state[:address] = address73@state[:props] = []74end75end7677def process_property78return if not @state[:props]79return if not @state[:props].length > 080@state[:root] ||= {}81@cobj = @state[:root]82property_parser(0)83end8485def property_parser(idx)86return if not @state[:props][idx]87case @state[:props][idx][0]88when "container", "ports", "entity", "properties"89@cobj[ @state[:props][idx][1] ] ||= {}90@cobj = @cobj[ @state[:props][idx][1] ]91else92@cobj[ state[:props][idx][1] ] = @text93end94property_parser(idx + 1)95end9697def report_host(&block)98@report_data = {99:ports => [:ignore],100:state => Msf::HostState::Alive,101:host => @state[:address]102}103104if @state[:root]["dns names"] and @state[:root]["dns names"].keys.length > 0105@report_data[:name] = @state[:root]["dns names"].keys.first106end107108if host_is_okay109@report_data.delete(:ports)110111db.emit(:address, @report_data[:host],&block) if block112host_object = db_report(:host, @report_data.merge(113:workspace => @args[:workspace] ) )114if host_object115db.report_import_note(host_object.workspace, host_object)116end117host_object118end119end120121def report_services(host_object)122return unless host_object.kind_of? ::Mdm::Host123124snames = {}125( @state[:root]["services"] || {} ).each_pair do |sname, sinfo|126sinfo.each_pair do |pinfo,pdata|127snames[pinfo] = sname.dup128end129end130131reported = []132if @state[:root]["tcp_ports"]133@state[:root]["tcp_ports"].each_pair do |pn, ps|134ps = "open" if ps == "listen"135svc = { :port => pn.to_i, :state => ps, :proto => 'tcp'}136if @state[:root]["Banners"] and @state[:root]["Banners"][pn.to_s]137svc[:info] = @state[:root]["Banners"][pn.to_s]138end139svc[:name] = snames["#{pn}-tcp"] if snames["#{pn}-tcp"]140reported << db_report(:service, svc.merge(:host => host_object))141end142end143144if @state[:root]["udp_ports"]145@state[:root]["udp_ports"].each_pair do |pn, ps|146ps = "open" if ps == "listen"147svc = { :port => pn.to_i, :state => ps, :proto => 'udp'}148svc[:name] = snames["#{pn}-udp"] if snames["#{pn}-tcp"]149reported << db_report(:service, svc.merge(:host => host_object))150end151end152153( @state[:root]["services"] || {} ).each_pair do |sname, sinfo|154sinfo.each_pair do |pinfo,pdata|155sport,sproto = pinfo.split("-")156db_report(:note, {157:host => host_object,158:port => sport.to_i,159:proto => sproto,160:ntype => "ci.#{sname}.fingerprint",161:data => pdata162})163end164end165166reported167end168169def report_vulns(host_object)170vuln_count = 0171block = @block172return unless host_object.kind_of? ::Mdm::Host173return unless @state[:root]["Vulnerabilities"]174@state[:root]["Vulnerabilities"].each_pair do |cve, vinfo|175vinfo.each_pair do |vname, vdesc|176data = {177:workspace => host_object.workspace,178:host => host_object,179:name => vname,180:info => vdesc,181:refs => [ cve ]182}183db_report(:vuln, data)184end185end186end187188end189end190end191192193194