module Rex::Parser::NokogiriDocMixin
Public Class Methods
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 45 def initialize(args,db,&block) @args = args @db = db @state = {} @state[:current_tag] = {} @block = block if block @report_data = {:wspace => args[:wspace]} @nx_console_id = args[:nx_console_id] super() end
Public Instance Methods
Turn XML attribute pairs in to more workable hashes (there are better Enumerable tricks in Ruby 1.9, but ignoring for now)
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 58 def attr_hash(attrs) h = {} attrs.each {|k,v| h[k] = v} h end
Effectively the same as characters()
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 217 def cdata_block(text) return unless @state[:has_text] @text ||= "" @text << text end
This breaks xml-encoded characters, so need to append. It's on the end_element tag name to turn the appending off and clear out the data.
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 210 def characters(text) return unless @state[:has_text] @text ||= "" @text << text end
Circumvent the unknown attribute logging by the various reporters. They seem to be there just for debugging anyway.
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 139 def db_report(table, data) raise "Data should be a hash" unless data.kind_of? Hash nonempty_data = data.reject {|k,v| v.nil?} valid_attrs = db_valid_attributes(table) raise "Unknown table `#{table}'" if valid_attrs.empty? case table when :note, :web_site, :web_page, :web_form, :web_vuln just_the_facts = nonempty_data else just_the_facts = nonempty_data.select {|k,v| valid_attrs.include? k.to_s.to_sym} end return nil if just_the_facts.empty? just_the_facts[:task] = @args[:task] db.send("report_#{table}", just_the_facts) end
XXX: It would be better to either have a single registry of acceptable keys if we're going to alert on bad ones, or to be more forgiving if the caller is this thing. There is basically no way to tell if report_host()'s tastes are going to change with this scheme.
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 159 def db_valid_attributes(table) case table.to_s.to_sym when :host ::Mdm::Host.new.attribute_names.map {|x| x.to_sym} | [:host, :workspace] when :service ::Mdm::Service.new.attribute_names.map {|x| x.to_sym} | [:host, :host_name, :mac, :workspace] when :vuln ::Mdm::Vuln.new.attribute_names.map {|x| x.to_sym} | [:host, :refs, :workspace, :port, :proto, :details, :exploited_at] when :vuln_details ::Mdm::VulnDetails.new.attribute_names.map {|x| x.to_sym} | [ :key ] when :host_details ::Mdm::HostDetails.new.attribute_names.map {|x| x.to_sym} | [ :key ] when :note, :web_site, :web_page, :web_form, :web_vuln # These guys don't complain [:anything] else [] end end
XXX: Document classes ought to define this
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 133 def determine_port_state(v) return v end
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 223 def end_document block = @block return unless @report_type_ok unless @state[:current_tag].empty? missing_ends = @state[:current_tag].keys.map {|x| "'#{x}'"}.join(", ") msg = "Warning, the provided file is incomplete, and there may be missing\n" msg << "data. The following tags were not closed: #{missing_ends}." db.emit(:warning,msg,&block) if block end end
If there's an address, it's not on the blacklist, it has ports, and the port list isn't empty… it's okay.
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 120 def host_is_okay return false unless @report_data[:host] return false unless valid_ip(@report_data[:host]) return false unless @report_data[:state] == Msf::HostState::Alive if @args[:blacklist] return false if @args[:blacklist].include?(@report_data[:host]) end return false unless @report_data[:ports] return false if @report_data[:ports].empty? return true end
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 113 def in_tag(tagname) @state[:current_tag].keys.include? tagname end
Nokogiri 1.4.4 (and presumably beyond) generates attrs as pairs, like [[“value1”,“foo”],] (but not hashes for some reason). 1.4.3.1 (and presumably 1.4.3.x and prior) generates attrs as a flat array of strings. We want array_pairs.
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 186 def normalize_attrs(attrs) attr_pairs = [] case attrs.first when Array, NilClass attr_pairs = attrs when String attrs.each_index {|i| next if i % 2 == 0 attr_pairs << [attrs[i-1],attrs[i]] } else # Wow, yet another format! It's either from the distant past or distant future. raise ::Msf::DBImportError.new("Unknown format for XML attributes. Please check your Nokogiri version.") end return attr_pairs end
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 70 def normalize_ref(ref_type, ref_value) return if ref_type.nil? || ref_type.empty? || ref_value.nil? || ref_value.empty? ref_value = ref_value.strip ref_type = ref_type.strip.upcase ret = case ref_type when "CVE" ref_value.gsub("CAN", "CVE") when "MS" if ref_value =~ /^MS[0-9]/ "MSB-#{ref_value}" else "MSB-MS#{ref_value}" end when "URL", "BID" "#{ref_type}-#{ref_value}" when "APPLE" ref_value when "XF" if ref_value =~ /\((\d+)\)$/ "#{ref_type}-#{$1}" else "#{ref_type}-#{ref_value}" end else # Handle others? "#{ref_type}-#{ref_value}" end return ret end
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 100 def normalize_references(orig_refs) return [] unless orig_refs refs = [] orig_refs.each do |ref_hash| ref_hash_sym = Hash[ref_hash.map {|k, v| [k.to_sym, v] }] ref_type = ref_hash_sym[:source].to_s.strip.upcase ref_value = ref_hash_sym[:value].to_s.strip refs << normalize_ref(ref_type, ref_value) end return refs.compact.uniq end
# File lib/rex/parser/nokogiri_doc_mixin.rb, line 64 def valid_ip(addr) valid = false valid = ::Rex::Socket::RangeWalker.new(addr).valid? rescue false !!valid end