class Rex::Parser::CIDocument

Attributes

text[R]

Public Class Methods

new(*args) click to toggle source
Calls superclass method Rex::Parser::NokogiriDocMixin::new
# File lib/rex/parser/ci_nokogiri.rb, line 15
def initialize(*args)
  super(*args)
  @state[:has_text] = true
end

Public Instance Methods

end_element(name=nil) click to toggle source

When we exit a tag, this is triggered.

# File lib/rex/parser/ci_nokogiri.rb, line 46
def end_element(name=nil)
  block = @block
  case name
  when "entity" # Wrap it up
    if @state[:address]
      host_object = report_host &block
      report_services(host_object)
      report_vulns(host_object)
    end
    # Reset the state once we close a host
    @report_data = {:wspace => @args[:wspace]}
    @state[:root] = {}
  when "property"
    if @state[:props]
      @text.strip! if @text
      process_property
      @state[:props].pop
    end
  end
  @state[:path].pop
  @text = nil
end
process_property() click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 78
def process_property
  return if not @state[:props]
  return if not @state[:props].length > 0
  @state[:root] ||= {}
  @cobj = @state[:root]
  property_parser(0)
end
property_parser(idx) click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 86
def property_parser(idx)
  return if not @state[:props][idx]
  case @state[:props][idx][0]
  when "container", "ports", "entity", "properties"
    @cobj[ @state[:props][idx][1] ] ||= {}
    @cobj = @cobj[ @state[:props][idx][1] ]
  else
    @cobj[ state[:props][idx][1] ] = @text
  end
  property_parser(idx + 1)
end
record_device(info) click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 69
def record_device(info)
  if info["class"] and info["class"] == "host" and info["name"]
    address = info["name"].to_s.gsub(/^.*\//, '')
    return if address !~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/
    @state[:address] = address
    @state[:props]   = []
  end
end
report_host(&block) click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 98
def report_host(&block)
  @report_data = {
    :ports  => [:ignore],
    :state  => Msf::HostState::Alive,
    :host   => @state[:address]
  }

  if @state[:root]["dns names"] and @state[:root]["dns names"].keys.length > 0
    @report_data[:name] = @state[:root]["dns names"].keys.first
  end

  if host_is_okay
    @report_data.delete(:ports)

    db.emit(:address, @report_data[:host],&block) if block
    host_object = db_report(:host, @report_data.merge(
      :workspace => @args[:wspace] ) )
    if host_object
      db.report_import_note(host_object.workspace, host_object)
    end
    host_object
  end
end
report_services(host_object) click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 122
def report_services(host_object)
  return unless host_object.kind_of? ::Mdm::Host

  snames = {}
  ( @state[:root]["services"] || {} ).each_pair do |sname, sinfo|
    sinfo.each_pair do |pinfo,pdata|
      snames[pinfo] = sname.dup
    end
  end

  reported = []
  if @state[:root]["tcp_ports"]
    @state[:root]["tcp_ports"].each_pair do |pn, ps|
      ps = "open" if ps == "listen"
      svc = { :port => pn.to_i, :state => ps, :proto => 'tcp'}
      if @state[:root]["Banners"] and @state[:root]["Banners"][pn.to_s]
        svc[:info] = @state[:root]["Banners"][pn.to_s]
      end
      svc[:name] = snames["#{pn}-tcp"] if snames["#{pn}-tcp"]
      reported << db_report(:service, svc.merge(:host => host_object))
    end
  end

  if @state[:root]["udp_ports"]
    @state[:root]["udp_ports"].each_pair do |pn, ps|
      ps = "open" if ps == "listen"
      svc = { :port => pn.to_i, :state => ps, :proto => 'udp'}
      svc[:name] = snames["#{pn}-udp"] if snames["#{pn}-tcp"]
      reported << db_report(:service, svc.merge(:host => host_object))
    end
  end

  ( @state[:root]["services"] || {} ).each_pair do |sname, sinfo|
    sinfo.each_pair do |pinfo,pdata|
      sport,sproto = pinfo.split("-")
      db_report(:note, {
        :host => host_object,
        :port => sport.to_i,
        :proto => sproto,
        :ntype => "ci.#{sname}.fingerprint",
        :data => pdata
      })
    end
  end

  reported
end
report_vulns(host_object) click to toggle source
# File lib/rex/parser/ci_nokogiri.rb, line 170
def report_vulns(host_object)
  vuln_count = 0
  block = @block
  return unless host_object.kind_of? ::Mdm::Host
  return unless @state[:root]["Vulnerabilities"]
  @state[:root]["Vulnerabilities"].each_pair do |cve, vinfo|
    vinfo.each_pair do |vname, vdesc|
      data = {
        :workspace => host_object.workspace,
        :host => host_object,
        :name => vname,
        :info => vdesc,
        :refs => [ cve ]
      }
      db_report(:vuln, data)
    end
  end
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/ci_nokogiri.rb, line 23
def start_element(name=nil,attrs=[])
  attrs = normalize_attrs(attrs)
  block = @block

  r = { :e => name }
  attrs.each { |pair| r[pair[0]] = pair[1] }

  if @state[:path]
    @state[:path].push r
  end

  case name
  when "entity"
    @state[:path] = [ r ]
    record_device(r)
  when "property"
    return if not @state[:address]
    return if not @state[:props]
    @state[:props] << [ r["type"], r["key"]]
  end
end