Skip to content
Permalink
Browse files

Land #11941, add support for module aliases

  • Loading branch information...
busterb committed Jun 11, 2019
2 parents c79d86e + deb31d7 commit fa09b239e84b7520a9cb360397a07f800c8947e4
@@ -34,22 +34,22 @@ def host(eval_host)

private

# Tests for various service conditions by comparing the module's full_name (which
# Tests for various service conditions by comparing the module's fullname (which
# is basically a pathname) to the intended target service record. The service.info
# column is tested against a regex in most/all cases and "false" is returned in the
# event of a match between an incompatible module and service fingerprint.
def exploit_filter_by_service(mod, serv)

# Filter out Unix vs Windows exploits for SMB services
return true if (mod.full_name =~ /\/samba/ and serv.info.to_s =~ /windows/i)
return true if (mod.full_name =~ /\/windows/ and serv.info.to_s =~ /samba|unix|vxworks|qnx|netware/i)
return true if (mod.full_name =~ /\/netware/ and serv.info.to_s =~ /samba|unix|vxworks|qnx/i)
return true if (mod.fullname =~ /\/samba/ and serv.info.to_s =~ /windows/i)
return true if (mod.fullname =~ /\/windows/ and serv.info.to_s =~ /samba|unix|vxworks|qnx|netware/i)
return true if (mod.fullname =~ /\/netware/ and serv.info.to_s =~ /samba|unix|vxworks|qnx/i)

# Filter out IIS exploits for non-Microsoft services
return true if (mod.full_name =~ /\/iis\/|\/isapi\// and (serv.info.to_s !~ /microsoft|asp/i))
return true if (mod.fullname =~ /\/iis\/|\/isapi\// and (serv.info.to_s !~ /microsoft|asp/i))

# Filter out Apache exploits for non-Apache services
return true if (mod.full_name =~ /\/apache/ and serv.info.to_s !~ /apache|ibm/i)
return true if (mod.fullname =~ /\/apache/ and serv.info.to_s !~ /apache|ibm/i)

false
end
@@ -123,7 +123,7 @@ def import(args={}, &block)
# Module names that match this vulnerability
matched = mrefs.values_at(*(vuln.refs.map { |x| x.name.upcase } & mrefs.keys)).map { |x| x.values }.flatten.uniq
next if matched.empty?
match_names = matched.map { |mod| mod.full_name }
match_names = matched.map { |mod| mod.fullname }

second_pass_services = []

@@ -31,12 +31,21 @@ def promptname
def shortname
refname.split('/').last
end

#
# Returns a list of alternate names the module might go by.
#
def aliases
const_defined?(:Aliases) ? const_get(:Aliases) : []
end
end

#
# Instance Methods
#

attr_accessor :aliased_as

#
# Returns the module's framework full reference name. This is the
# short name that end-users work with (refname) plus the type
@@ -45,7 +54,7 @@ def shortname
# payloads/windows/shell/reverse_tcp
#
def fullname
self.class.fullname
aliased_as || self.class.fullname
end

#
@@ -55,16 +64,16 @@ def fullname
# windows/shell/reverse_tcp
#
def refname
self.class.refname
fullname.sub(type + '/', '')
end

#
# Returns the module's framework prompt-friendly name.
#
# reverse_tcp
# windows/shell/reverse_tcp
#
def promptname
self.class.promptname
refname
end

#
@@ -73,6 +82,10 @@ def promptname
# reverse_tcp
#
def shortname
self.class.shortname
refname.split('/').last
end

def aliases
self.class.aliases
end
end
@@ -64,7 +64,10 @@ def [](key)
# Otherwise, we step through all sets until we find one that
# matches.
# @return (see Msf::ModuleSet#create)
def create(name)
def create(name, aliased_as: nil)
# First, a direct alias check
return create(self.aliases[name], aliased_as: name) if self.aliases[name]

# Check to see if it has a module type prefix. If it does,
# try to load it from the specific module set for that type.
names = name.split("/")
@@ -88,13 +91,21 @@ def create(name)
else
# Then we don't have a type, so we have to step through each set
# to see if we can create this module.
module_set_by_type.each do |_, set|
module_reference_name = names.join("/")
module_instance = set.create(module_reference_name)
module_set_by_type.each do |type, set|
if aliased = self.aliases["#{type}/#{name}"]
module_instance = create(aliased, aliased_as: "#{type}/#{name}")
else
module_reference_name = names.join("/")
module_instance = set.create(module_reference_name)
end
break if module_instance
end
end

if module_instance
module_instance.aliased_as = aliased_as
end

module_instance
end

@@ -125,6 +136,8 @@ def initialize(framework, types=Msf::MODULE_TYPES)
self.module_load_warnings = {}
self.module_paths = []
self.module_set_by_type = {}
self.aliases = {}
self.inv_aliases = self.aliases.invert

#
# from arguments
@@ -139,6 +152,8 @@ def initialize(framework, types=Msf::MODULE_TYPES)

protected

attr_accessor :aliases, :inv_aliases

# This method automatically subscribes a module to whatever event
# providers it wishes to monitor. This can be used to allow modules
# to automatically execute or perform other tasks when certain
@@ -170,6 +170,10 @@ def module_info_by_path_from_database!(allowed_paths=[""])
:parent_path => parent_path,
:modification_time => module_metadata.mod_time
}
module_metadata.aliases.each do |a|
self.aliases[a] = module_metadata.fullname
end
self.inv_aliases[module_metadata.fullname] = module_metadata.aliases unless module_metadata.aliases.empty?

typed_module_set = module_set(type)

@@ -86,6 +86,22 @@ def on_module_load(class_or_module, type, reference_name, info={})

# Notify the framework that a module was loaded
framework.events.on_module_load(reference_name, class_or_module)

# Clear and add aliases, if any (payloads cannot)

if class_or_module.respond_to?(:fullname) && aliased_as = self.inv_aliases[class_or_module.fullname]
aliased_as.each do |a|
self.aliases.delete a
end
self.inv_aliases.delete class_or_module.fullname
end

if class_or_module.respond_to? :aliases
class_or_module.aliases.each do |a|
self.aliases[a] = class_or_module.fullname
end
self.inv_aliases[class_or_module.fullname] = class_or_module.aliases unless class_or_module.aliases.empty?
end
end

protected
@@ -13,6 +13,13 @@ def reload_module(mod)
metasploit_class = mod
end

if aliased_as = self.inv_aliases[metasploit_class.fullname]
aliased_as.each do |a|
self.aliases.delete a
end
self.inv_aliases.delete metasploit_class.fullname
end

namespace_module = metasploit_class.parent
loader = namespace_module.loader
loader.reload_module(mod)
@@ -26,6 +33,8 @@ def reload_modules
module_set_by_type[type].clear
init_module_set(type)
end
self.aliases.clear
self.inv_aliases.clear

# default the count to zero the first time a type is accessed
count_by_type = Hash.new(0)
@@ -20,7 +20,7 @@ def all_remote_exploit_maps
get_metadata.each do |exploit|
# expand this in future to be more specific about remote exploits.
next unless exploit.type == "exploit"
fullname = exploit.full_name
fullname = exploit.fullname
exploit.references.each do |reference|
next if reference =~ /^URL/
ref = reference
@@ -12,7 +12,9 @@ class Obj
# @return [String]
attr_reader :name
# @return [String]
attr_reader :full_name
attr_reader :fullname
# @return [Array<String>]
attr_reader :aliases
# @return [Integer]
attr_reader :rank
# @return [Date]
@@ -59,7 +61,8 @@ def initialize(module_instance, obj_hash = nil)
end

@name = module_instance.name
@full_name = module_instance.fullname
@fullname = module_instance.fullname
@aliases = module_instance.aliases
@disclosure_date = module_instance.disclosure_date
@rank = module_instance.rank.to_i
@type = module_instance.type
@@ -110,7 +113,8 @@ def initialize(module_instance, obj_hash = nil)
def to_json(*args)
{
'name' => @name,
'full_name' => @full_name,
'fullname' => @fullname,
'aliases' => @aliases,
'rank' => @rank,
'disclosure_date' => @disclosure_date.nil? ? nil : @disclosure_date.to_s,
'type' => @type,
@@ -159,7 +163,8 @@ def path

def init_from_hash(obj_hash)
@name = obj_hash['name']
@full_name = obj_hash['full_name']
@fullname = obj_hash['fullname']
@aliases = obj_hash['aliases'] || []
@disclosure_date = obj_hash['disclosure_date'].nil? ? nil : Time.parse(obj_hash['disclosure_date'])
@rank = obj_hash['rank']
@type = obj_hash['type']
@@ -194,7 +199,7 @@ def sort_platform_string

def force_encoding(encoding)
@name.force_encoding(encoding)
@full_name.force_encoding(encoding)
@fullname.force_encoding(encoding)
@description.force_encoding(encoding)
@author.each {|a| a.force_encoding(encoding)}
@references.each {|r| r.force_encoding(encoding)}
@@ -6,7 +6,7 @@
module Msf::Modules::Metadata::Search

VALID_PARAMS =
%w[aka author authors arch cve bid edb check date disclosure_date description full_name fullname mod_time
%w[aka author authors arch cve bid edb check date disclosure_date description fullname fullname mod_time
name os platform path port rport rank ref ref_name reference references target targets text type]

#
@@ -70,8 +70,8 @@ def is_match(params, module_metadata)
match = [keyword, search_term] if module_metadata.disclosure_date.to_s =~ regex
when 'description'
match = [keyword, search_term] if module_metadata.description =~ regex
when 'full_name', 'fullname'
match = [keyword, search_term] if module_metadata.full_name =~ regex
when 'fullname'
match = [keyword, search_term] if module_metadata.fullname =~ regex
when 'mod_time'
match = [keyword, search_term] if module_metadata.mod_time.to_s =~ regex
when 'name'
@@ -82,7 +82,7 @@ def is_match(params, module_metadata)
match = [keyword, search_term] if module_metadata.targets.any? { |target| target =~ regex }
end
when 'path'
match = [keyword, search_term] if module_metadata.full_name =~ regex
match = [keyword, search_term] if module_metadata.fullname =~ regex
when 'port', 'rport'
match = [keyword, search_term] if module_metadata.rport.to_s =~ regex
when 'rank'
@@ -120,7 +120,7 @@ def is_match(params, module_metadata)
when 'target', 'targets'
match = [keyword, search_term] if module_metadata.targets.any? { |target| target =~ regex }
when 'text'
terms = [module_metadata.name, module_metadata.full_name, module_metadata.description] + module_metadata.references + module_metadata.author + (module_metadata.notes['AKA'] || [])
terms = [module_metadata.name, module_metadata.fullname, module_metadata.description] + module_metadata.references + module_metadata.author + (module_metadata.notes['AKA'] || [])

if module_metadata.targets
terms = terms + module_metadata.targets
@@ -155,7 +155,6 @@ def get_fields(module_metadata, fields)
:cve => 'references',
:edb => 'references',
:bid => 'references',
:fullname => 'full_name',
:os => 'platform',
:port => 'rport',
:reference => 'references',
@@ -711,7 +711,7 @@ def rpc_analyze_host(xopts)
h_result[:modules].each do |mod|
mod_detail = {}
mod_detail[:mtype] = mod.type
mod_detail[:mname] = mod.full_name
mod_detail[:mname] = mod.fullname
host_detail[:modules] << mod_detail
end
end
@@ -54,7 +54,7 @@ def cmd_analyze(*args)
host_result = framework.analyze.host(eval_host)
found_modules = host_result[:modules]
found_modules.each do |fnd_mod|
print_status(fnd_mod.full_name)
print_status(fnd_mod.fullname)
reported_module = true
end

@@ -335,7 +335,7 @@ def cmd_search_help
'check' => 'Modules that support the \'check\' method',
'date' => 'Modules with a matching disclosure date',
'description' => 'Modules with a matching description',
'full_name' => 'Modules with a matching full name',
'fullname' => 'Modules with a matching full name',
'mod_time' => 'Modules with a matching modification date',
'name' => 'Modules with a matching descriptive name',
'path' => 'Modules with a matching path',
@@ -403,7 +403,7 @@ def cmd_search(*args)
@module_search_results.each do |m|
tbl << [
count += 1,
m.full_name,
m.fullname,
m.disclosure_date.nil? ? '' : m.disclosure_date.strftime("%Y-%m-%d"),
RankingName[m.rank].to_s,
m.check ? 'Yes' : 'No',
@@ -412,7 +412,7 @@ def cmd_search(*args)
end

if @module_search_results.length == 1 && use
used_module = @module_search_results.first.full_name
used_module = @module_search_results.first.fullname
cmd_use(used_module, true)
end
rescue ArgumentError
@@ -650,7 +650,7 @@ def cmd_use(*args)
# Use a module by search index
if mod_index
return if mod_index < 0 || @module_search_results[mod_index].nil?
mod_name = @module_search_results[mod_index].full_name
mod_name = @module_search_results[mod_index].fullname
end

# See if the supplied module name has already been resolved
@@ -15,6 +15,10 @@ class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute

Aliases = [
'auxiliary/scanner/smb/login'
]

def proto
'smb'
end
@@ -8,6 +8,10 @@ class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner

Aliases = [
'auxiliary/scanner/smtp/enum'
]

def initialize
super(
'Name' => 'SMTP User Enumeration Utility',

0 comments on commit fa09b23

Please sign in to comment.
You can’t perform that action at this time.