Path: blob/master/lib/msf/core/module/reference.rb
52183 views
# -*- coding: binary -*-12###3#4# A reference to some sort of information. This is typically a URL, but could5# be any type of referential value that people could use to research a topic.6#7###8class Msf::Module::Reference910#11# Serialize a reference from a string.12#13def self.from_s(str)14return self.new(str)15end1617#18# Initializes a reference from a string.19#20def initialize(in_str)21self.str = in_str22end2324#25# Compares references to see if they're equal.26#27def ==(tgt)28return (tgt.to_s == to_s)29end3031#32# Returns the reference as a string.33#34def to_s35return self.str36end3738#39# Serializes the reference instance from a string.40#41def from_s(in_str)42self.str = in_str43end4445#46# The reference string.47#48attr_reader :str4950protected5152attr_writer :str # :nodoc:5354end5556###57#58# A reference to a website.59#60###61class Msf::Module::SiteReference < Msf::Module::Reference6263#64# Class method that translates a URL into a site reference instance.65#66def self.from_s(str)67instance = self.new6869if (instance.from_s(str) == false)70return nil71end7273return instance74end7576#77# Initializes a site reference from an array. ary[0] is the site and78# ary[1] is the site context identifier, such as CVE.79# ary[2] is optional and can be used for additional context (e.g., repo for GHSA)80#81def self.from_a(ary)82return nil if (ary.length < 2)83# Reject if first element is an array (nested array structure)84return nil if ary[0].kind_of?(Array)8586self.new(ary[0], ary[1], ary[2])87end8889#90# Initialize the site reference.91# If you're updating the references, please also update:92# * tools/module_reference.rb93# * https://docs.metasploit.com/docs/development/developing-modules/module-metadata/module-reference-identifiers.html94#95def initialize(in_ctx_id = 'Unknown', in_ctx_val = '', in_ctx_repo = nil)96# Ensure ctx_id and ctx_val are strings (handle constants like ATT&CK techniques)97in_ctx_id = in_ctx_id.to_s if in_ctx_id.respond_to?(:to_s) && !in_ctx_id.is_a?(String)98in_ctx_val = in_ctx_val.to_s if in_ctx_val.respond_to?(:to_s) && !in_ctx_val.is_a?(String)99100self.ctx_id = in_ctx_id101self.ctx_val = in_ctx_val102self.ctx_repo = in_ctx_repo103104if in_ctx_id == 'CVE'105self.site = "https://nvd.nist.gov/vuln/detail/CVE-#{in_ctx_val}"106elsif in_ctx_id == 'CWE'107self.site = "https://cwe.mitre.org/data/definitions/#{in_ctx_val}.html"108elsif in_ctx_id == 'BID'109self.site = "http://www.securityfocus.com/bid/#{in_ctx_val}"110elsif in_ctx_id == 'MSB'111year = in_ctx_val[2..3]112century = year[0] == '9' ? '19' : '20'113self.site = "https://docs.microsoft.com/en-us/security-updates/SecurityBulletins/#{century}#{year}/#{in_ctx_val}"114elsif in_ctx_id == 'EDB'115self.site = "https://www.exploit-db.com/exploits/#{in_ctx_val}"116elsif in_ctx_id == 'US-CERT-VU'117self.site = "https://www.kb.cert.org/vuls/id/#{in_ctx_val}"118elsif in_ctx_id == 'ZDI'119self.site = "http://www.zerodayinitiative.com/advisories/ZDI-#{in_ctx_val}"120elsif in_ctx_id == 'WPVDB'121self.site = "https://wpscan.com/vulnerability/#{in_ctx_val}"122elsif in_ctx_id == 'PACKETSTORM'123self.site = "https://packetstormsecurity.com/files/#{in_ctx_val}"124elsif in_ctx_id == 'GHSA'125# Handle both formats: with or without GHSA- prefix126ghsa_id = in_ctx_val.start_with?('GHSA-') ? in_ctx_val : "GHSA-#{in_ctx_val}"127# Use repo-specific URL if repo is provided, otherwise use global format128if in_ctx_repo && !in_ctx_repo.empty?129self.site = "https://github.com/#{in_ctx_repo}/security/advisories/#{ghsa_id}"130else131self.site = "https://github.com/advisories/#{ghsa_id}"132end133elsif in_ctx_id == 'OSV'134self.site = "https://osv.dev/vulnerability/#{in_ctx_val}"135elsif in_ctx_id == 'URL'136self.site = in_ctx_val.to_s137elsif in_ctx_id == 'LOGO'138self.site = "Logo: #{in_ctx_val}"139elsif in_ctx_id == 'SOUNDTRACK'140self.site = "Soundtrack: #{in_ctx_val}"141elsif in_ctx_id == 'ATT&CK'142match = in_ctx_val.match(/\A(?<category>[A-Z]+)(?<id>[\d.]+)\z/)143path = Msf::Mitre::Attack::Categories::PATHS[match[:category]]144id_path = match[:id].gsub('.', '/')145self.site = "https://attack.mitre.org/#{path}/#{match[:category]}#{id_path}/"146else147self.site = in_ctx_id148self.site += " (#{in_ctx_val})" if (in_ctx_val)149end150end151152#153# Returns the absolute site URL.154#155def to_s156return site || ''157end158159#160# Serializes a site URL string.161#162def from_s(str)163if (/(http:\/\/|https:\/\/|ftp:\/\/)/.match(str))164self.site = str165self.ctx_id = 'URL'166self.ctx_val = self.site167else168return false169end170171return true172end173174#175# The site being referenced.176#177attr_reader :site178#179# The context identifier of the site, such as CVE.180#181attr_reader :ctx_id182#183# The context value of the reference, such as MS02-039184#185attr_reader :ctx_val186#187# The context repository for GHSA references (optional)188#189attr_reader :ctx_repo190191protected192193attr_writer :site, :ctx_id, :ctx_val, :ctx_repo194195end196197198