class NTOSpider::Vuln

This class represents each of the vulnerabilities reported in the NTOSpider VulnerabilitiesSummary.xml file as <Vuln> entities.

It provides a convenient way to access the information scattered all over the XML entities.

Instead of providing separate methods for each supported property we rely on Ruby's method_missing to do most of the work.

Attributes

xml[RW]

Public Class Methods

new(xml_node) click to toggle source

Accepts an XML node from Nokogiri::XML.

# File lib/ntospider/vuln.rb, line 13
def initialize(xml_node)
  @xml = xml_node
end

Public Instance Methods

method_missing(method, *args) click to toggle source

This method is invoked by Ruby when a method that is not defined in this instance is called.

In our case we inspect the @method@ parameter and try to find the attribute, simple descendent or collection that it maps to in the XML tree.

Calls superclass method
# File lib/ntospider/vuln.rb, line 45
def method_missing(method, *args)
  # We could remove this check and return nil for any non-recognized tag.
  # The problem would be that it would make tricky to debug problems with
  # typos. For instance: <>.potr would return nil instead of raising an
  # exception
  unless supported_tags.include?(method)
    super
    return
  end

  # First we try the attributes. In Ruby we use snake_case, but in XML
  # CamelCase is used for some attributes
  translations_table = {
    capec:     'CAPEC',
    dissa_asc: 'DISSA_ASC',
    owasp2007: 'OWASP2007',
    owasp2010: 'OWASP2010',
    owasp2013: 'OWASP2013',
    oval:      'OVAL',
    wasc:      'WASC'
  }

  method_name = translations_table.fetch(method, method.to_s.camelcase)

  # no attributes in the <issue> node
  # return @xml.attributes[method_name].value if @xml.attributes.key?(method_name)

  # Then we try simple children tags: name, type, ...
  tag = @xml.at_xpath("./#{method_name}")
  if tag && !tag.text.blank?
    if tags_with_html_content.include?(method)
      return cleanup_html(tag.text)
    else
      return tag.text
    end
  else
    # nothing found, the tag is valid but not present in this Vuln
    return nil
  end
end
respond_to?(method, include_private=false) click to toggle source

This allows external callers (and specs) to check for implemented properties

Calls superclass method
# File lib/ntospider/vuln.rb, line 34
def respond_to?(method, include_private=false)
  return true if supported_tags.include?(method.to_sym)
  super
end
supported_tags() click to toggle source

List of supported tags. They can be attributes, simple descendants or collections (e.g. <references/>, <tags/>)

# File lib/ntospider/vuln.rb, line 19
    def supported_tags
      [
        # attributes

        # simple tags
        :attack_class, :attack_score, :attack_type, :attack_value, :capec,
        :cwe_id, :description, :dissa_asc, :normalized_url, :oval, :owasp2007,
        :owasp2010, :owasp2013, :recommendation, :vuln_method, :vuln_param,
        :vuln_type, :vuln_url, :web_site
        # nested tags
      ]
end

Private Instance Methods

cleanup_html(source) click to toggle source
# File lib/ntospider/vuln.rb, line 88
def cleanup_html(source)
  result = source.dup
  result.gsub!(/&quot;/, '"')
  result.gsub!(/&amp;/, '&')
  result.gsub!(/&lt;/, '<')
  result.gsub!(/&gt;/, '>')

  result.gsub!(/<b>(.*?)<\/b>/, '*\1*')
  result.gsub!(/<br\/>/, "\n")
  result.gsub!(/<br>/, "\n")
  result.gsub!(/<font.*?>(.*?)<\/font>/m, '\1')
  result.gsub!(/<h2>(.*?)<\/h2>/, '*\1*')
  result.gsub!(/<i>(.*?)<\/i>/, '\1')
  result.gsub!(/<p>(.*?)<\/p>/m, '\1')
  result.gsub!(/<pre.*?>(.*?)<\/pre>/m){|m| "\n\nbc.. #{ $1 }\n\np.  \n" }

  result.gsub!(/<ul>/, "\n")
  result.gsub!(/<\/ul>/, "\n")
  result.gsub!(/<li>/, "\n* ")
  result.gsub!(/<\/li>/, "\n")

  result
end
tags_with_html_content() click to toggle source

Some of the values have embedded HTML content that we need to strip

# File lib/ntospider/vuln.rb, line 113
def tags_with_html_content
  [:description, :recommendation]
end