class Netsparker::Vulnerability
This class represents each of the /netsparker/vulnerability elements in the Netsparker
XML document.
It provides a convenient way to access the information scattered all over the XML in attributes and nested tags.
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/netsparker/vulnerability.rb, line 14 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/netsparker/vulnerability.rb, line 62 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 # Any fields where a simple .camelcase() won't work we need to translate, # this includes acronyms (e.g. :cwe would become 'Cwe') and simple nested # tags. translations_table = { actions_to_take: 'actionsToTake', classification_asvs40: 'classification/ASVS40', classification_capec: 'classification/CAPEC', classification_cwe: 'classification/CWE', classification_cvss_vector: 'classification/CVSS/vector', classification_cvss_base_value: "classification/CVSS/score/type[text()='Base']/../value", classification_cvss_base_severity: "classification/CVSS/score/type[text()='Base']/../severity", classification_cvss_environmental_value: "classification/CVSS/score/type[text()='Environmental']/../value", classification_cvss_environmental_severity: "classification/CVSS/score/type[text()='Environmental']/../severity", classification_cvss_temporal_value: "classification/CVSS/score/type[text()='Temporal']/../value", classification_cvss_temporal_severity: "classification/CVSS/score/type[text()='Temporal']/../severity", classification_disastig: 'classification/DISASTIG', classification_hipaa: 'classification/HIPAA', classification_iso27001: 'classification/ISO27001', classification_nistsp80053: 'classification/NISTSP80053', classification_owasp2013: 'classification/OWASP2013', classification_owasp2017: 'classification/OWASP2017', classification_owasppc: 'classification/OWASPPC', classification_pci31: 'classification/PCI31', classification_pci32: 'classification/PCI32', classification_wasc: 'classification/WASC', external_references: 'externalReferences', remedy_references: 'remedyReferences', required_skills_for_exploitation: 'requiredSkillsForExploitation' } method_name = translations_table.fetch(method, method.to_s) # first we try the attributes: # return @xml.attributes[method_name].value if @xml.attributes.key?(method_name) # then we try the children tags tag = xml.at_xpath("./#{method_name}") if tag && !tag.text.blank? text = tag.text return tags_with_html_content.include?(method) ? cleanup_html(text) : text else return 'n/a' end # nothing found return nil 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/netsparker/vulnerability.rb, line 51 def respond_to?(method, include_private=false) return true if supported_tags.include?(method.to_sym) super end
Private Instance Methods
cleanup_html(source)
click to toggle source
# File lib/netsparker/vulnerability.rb, line 122 def cleanup_html(source) result = source.dup result.gsub!(/"/, '"') result.gsub!(/&/, '&') result.gsub!(/</, '<') result.gsub!(/>/, '>') result.gsub!(/'/, '\'') result.gsub!(/\<\!\[CDATA\[(.*?)\]\]\>/m, '\1') result.gsub!(/<b>(.*?)<\/b>/) { "*#{$1}*" } result.gsub!(/<i>(.*?)<\/i>/) { "_#{$1}_" } result.gsub!(/<em>(.*?)<\/em>/) { "*#{$1}*" } result.gsub!(/<h2>(.*?)<\/h2>/) { "*#{$1}*" } result.gsub!(/<strong>(.*?)<\/strong>/) { "*#{$1}* " } result.gsub!(/(<br>)|(<br(\s*)\/>)/, "\n") result.gsub!(/(<div>)|(<\/div>)/, "") result.gsub!(/<font.*?>(.*?)<\/font>/m, '\1') result.gsub!(/<p (.*?)>(.*?)<\/p>/) { "\n#{$2}\n" } result.gsub!(/<span(.*?)>(.*?)<\/span>/, '\2') result.gsub!(/<span(.*?)>|<\/span>/, "") result.gsub!(/(<p>)|(<\/p>)/, "\n") result.gsub!(/\n[a-z]\. /, "\n\* ") result.gsub!(/<a .*?href=(?:\"|\')(.*?)(?:\"|\').*?>(?:<i.*?<\/i>)?(.*?)<\/a>/i) { "\"#{$2.strip}\":#{$1.strip}" } result.gsub!(/<code><pre.*?>(.*?)<\/pre><\/code>/m) {|m| "\n\nbc.. #{$1}\n\np. \n" } result.gsub!(/<pre.*?>(.*?)<\/pre>/m) {|m| "\n\nbc.. #{$1}\n\np. \n" } result.gsub!(/<code>(.*?)<\/code>/m) {|m| "\n\nbc.. #{$1}\n\np. \n" } result.gsub!(/(<ul>)|(<\/ul>|(<ol>)|(<\/ol>))/, "\n") result.gsub!(/<li(.*?)>(.*?)<\/li>/m) {"\n* #{$2}\n" } result.gsub!(/<li>/, "\n* ") result.gsub!(/<\/li>/, "\n") result end