class Intrigue::Ident::Cpe
Public Class Methods
new(cpe_string)
click to toggle source
# File lib/cpe.rb, line 5 def initialize(cpe_string) @cpe = cpe_string x = _parse_cpe(@cpe) return nil unless x @vendor = x[:vendor] @product = x[:product] @version = x[:version] @variant = x[:variant] # TODO... currenty not used end
Public Instance Methods
<(another)
click to toggle source
# File lib/cpe.rb, line 17 def <(another) Gem::Version(@version) < Gem::Version(_parse_cpe(another[:version])) end
>(another)
click to toggle source
# File lib/cpe.rb, line 21 def >(another) Gem::Version(@version) > Gem::Version(_parse_cpe(another[:version])) end
vulns()
click to toggle source
hacktastic! matches vulns by CPE
# File lib/cpe.rb, line 26 def vulns # Set a data directory underneath our folder if we're not in the context of core if $intrigue_basedir nvd_data_directory = "#{$intrigue_basedir}/data/nvd" else nvd_data_directory = "#{File.expand_path('data/nvd', File.dirname(__FILE__))}" end # fail unless we have something to match return [] unless @version vulns = [] files = [ "#{nvd_data_directory}/nvdcve-1.0-2018.json", "#{nvd_data_directory}/nvdcve-1.0-2017.json", "#{nvd_data_directory}/nvdcve-1.0-2016.json", "#{nvd_data_directory}/nvdcve-1.0-2015.json", "#{nvd_data_directory}/nvdcve-1.0-2014.json", "#{nvd_data_directory}/nvdcve-1.0-2013.json", "#{nvd_data_directory}/nvdcve-1.0-2012.json", "#{nvd_data_directory}/nvdcve-1.0-2011.json" ] files.each do |f| puts "DEBUG Checking file: #{f}" next unless File.exist? f json = ::JSON.parse(File.open(f,"r").read) json["CVE_Items"].each do |v| # Note that the JSON has CVE stuff under a hash, so # pull that out separately (probably due to NVD responsibility vs Mitre) cve = v["cve"] # data sanity check unless cve["affects"] && cve["affects"]["vendor"] && cve["affects"]["vendor"]["vendor_data"] #puts "DEBUG No Affects data... #{cve["cve"]}" next end # check to make sure it includes our vendor vendors = cve["affects"]["vendor"]["vendor_data"].map{|x| x["vendor_name"].downcase } unless vendors.uniq.include? @vendor.downcase #vd = cve["affects"]["vendor"]["vendor_data"] #puts "DEBUG No vendor match: #{@vendor.downcase} in #{vendors.uniq.count} vendors..." next end # iterate through the heirarchy to get to product and version we can match on cve["affects"]["vendor"]["vendor_data"].each do |vd| #puts "DEBUG Checking Vendor Data #{vd}" vd["product"]["product_data"].each do |p| #puts "DEBUG Checking product #{p}" p["version"]["version_data"].each do |vd| next unless p["product_name"].downcase == @product.downcase #puts "DEBUG Matching: #{vd["version_value"]} with #{@version}" if vd["version_value"] >= @version #puts "MATCHED!" cve_id = cve["CVE_data_meta"]["ID"] #puts "CVE: #{cve_id}" # Get the CWE if we have it if cve["problemtype"] && cve["problemtype"]["problemtype_data"].first cwe_id = cve["problemtype"]["problemtype_data"].first["description"].first["value"] #puts "CWE: #{cwe_id}" end # Get the CVSS data if we have it if v["impact"] cvss_v2_score = v["impact"]["baseMetricV2"]["cvssV2"]["baseScore"] cvss_v2_vector = v["impact"]["baseMetricV2"]["cvssV2"]["vectorString"] #puts "CVSS v2: #{cvss_v2}" # v3 only goes back to 2016 if v["impact"]["baseMetricV3"] cvss_v3_score = v["impact"]["baseMetricV3"]["cvssV3"]["baseScore"] cvss_v3_vector = v["impact"]["baseMetricV3"]["cvssV3"]["vectorString"] #puts "CVSS v3: #{cvss_v3}" end end # create a hash with the vuln's data vuln = { cve_id: cve_id, cwe_id: cwe_id, cvss_v2: {score: cvss_v2_score, vector: cvss_v2_vector }, cvss_v3: {score: cvss_v3_score, vector: cvss_v3_vector } } #puts "DEBUG Vuln: #{vuln}" vulns << vuln end end end end end end #puts "DEBUG Sending #{vulns.uniq.count} vulns" vulns.uniq end
Private Instance Methods
_parse_cpe(string)
click to toggle source
# File lib/cpe.rb, line 135 def _parse_cpe(string) m = string.match(/^cpe:2.3:[o|a|s|h]:(.*?):.*$/) vendor = m[1] if m #puts "DEBUG Got Vendor: #{vendor}" m = string.match(/^cpe:2.3:[o|a|s|h]:.*?:(.*?):.*$/) product = m[1] if m #puts "DEBUG Got Product: #{product}" m = string.match(/^cpe:2.3:[o|a|s|h]:.*?:.*?:(.*)$/) version = m[1] if m #puts "DEBUG Got Version: #{version}" # if version has parens, only use the stuff priior (apache, nginx, etc) if version =~ /\(/ old_version = version #puts "DEBUG Splitting Version: #{version}" version = old_version.split("(").first.chomp #puts "DEBUG New Version: #{version}" variant = old_version.split("(").last.split(")").first.chomp #HACK #puts "DEBUG New Variant: #{variant}" end # if there's nothing to do here... return unless product && vendor && version # HACK... cleanup version if needed version = version.gsub(/\(.*/,"").gsub(/\+.*/,"").gsub(/-.*/,"").gsub(/\s.*/,"") parsed = { :vendor => vendor, :product => product, :version => version, :variant => variant } parsed end