refactor search to work with existing console search function, and expand console keyword options
parent
6c7650eec3
commit
2215cab7df
|
@ -4,9 +4,10 @@ module Msf::DBManager::Module
|
||||||
raise ::ArgumentError, "At least one search parameter must be provided." if opts.dup.except!(:fields).empty?
|
raise ::ArgumentError, "At least one search parameter must be provided." if opts.dup.except!(:fields).empty?
|
||||||
search_results = []
|
search_results = []
|
||||||
metadata = Msf::Modules::Metadata::Cache.instance.get_metadata
|
metadata = Msf::Modules::Metadata::Cache.instance.get_metadata
|
||||||
|
params = parse_params(opts)
|
||||||
metadata.each { |module_metadata|
|
metadata.each { |module_metadata|
|
||||||
if is_match(module_metadata, opts)
|
if Msf::Modules::Metadata::Cache.instance.matches(params, module_metadata)
|
||||||
search_results << get_fields(module_metadata, opts)
|
search_results << get_fields(opts, module_metadata)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
search_results
|
search_results
|
||||||
|
@ -16,95 +17,29 @@ module Msf::DBManager::Module
|
||||||
private
|
private
|
||||||
#######
|
#######
|
||||||
|
|
||||||
def is_match(metadata, params)
|
def parse_params(opts)
|
||||||
match = true
|
# Parse the query params and format the hash to match what the console search `is_match` function expects
|
||||||
params.each do |param, value|
|
# A param prefixed with '-' indicates "not", and will omit results matching that keyword
|
||||||
|
#
|
||||||
r = Regexp.new(Regexp.escape(value), true)
|
# Resulting Hash Example:
|
||||||
|
# {"platform"=>[["android"], []]} will match modules targeting the android platform
|
||||||
case param
|
# {"platform"=>[[], ["android"]]} will exclude modules targeting the android platform
|
||||||
when :app
|
params = {}
|
||||||
(match = match && value == 'client') if metadata.is_client
|
opts.each do |k, v|
|
||||||
(match = match && value == 'server') if metadata.is_server
|
key = k.to_s
|
||||||
when :author, :authors
|
unless key == "fields"
|
||||||
match = match && metadata.author.any? { |a| a =~ r}
|
params[key] = [ [], [] ]
|
||||||
when :arch
|
if v[0, 1] == '-'
|
||||||
match = match && metadata.arch =~ r
|
params[key][1] << v[1,v.length-1]
|
||||||
when :bid
|
else
|
||||||
match = match && metadata.references.any? { |ref| ref =~ /^bid\-/i and ref =~ r }
|
params[key][0] << v
|
||||||
when :cve
|
|
||||||
match = match && metadata.references.any? { |ref| ref =~ /^cve\-/i and ref =~ r }
|
|
||||||
when :edb
|
|
||||||
match = match && metadata.references.any? { |ref| ref =~ /^edb\-/i and ref =~ r }
|
|
||||||
when :description
|
|
||||||
match = match && metadata.description =~ r
|
|
||||||
when :date, :disclosure_date
|
|
||||||
match = match && metadata.disclosure_date.to_s =~ r
|
|
||||||
when :full_name, :fullname
|
|
||||||
match = match && metadata.full_name =~ r
|
|
||||||
when :is_client
|
|
||||||
match = match && value == (metadata.is_client).to_s
|
|
||||||
when :is_server
|
|
||||||
match = match && value == (metadata.is_server).to_s
|
|
||||||
when :is_install_path
|
|
||||||
match = match && value == (metadata.is_install_path).to_s
|
|
||||||
when :mod_time
|
|
||||||
match = match && metadata.mod_time.to_s =~ r
|
|
||||||
when :name
|
|
||||||
match = match && metadata.name =~ r
|
|
||||||
when :os, :platform
|
|
||||||
terms = [metadata.platform, metadata.arch]
|
|
||||||
if metadata.targets
|
|
||||||
terms = terms + metadata.targets
|
|
||||||
end
|
end
|
||||||
match = match && terms.any? { |term| term =~ r }
|
|
||||||
when :path
|
|
||||||
match = match && metadata.path =~ r
|
|
||||||
when :port, :rport
|
|
||||||
match = match && metadata.rport =~ r
|
|
||||||
when :rank
|
|
||||||
# Determine if param was prepended with gt, lt, gte, lte, or eq
|
|
||||||
# Ex: "lte300" should match all ranks <= 300
|
|
||||||
query_rank = value.dup
|
|
||||||
operator = query_rank[0, 3].tr("0-9", "")
|
|
||||||
matches_rank = metadata.rank == value.to_i
|
|
||||||
unless operator.empty?
|
|
||||||
query_rank.slice! operator
|
|
||||||
query_rank = query_rank.to_i
|
|
||||||
case operator
|
|
||||||
when 'gt'
|
|
||||||
matches_rank = metadata.rank.to_i > query_rank
|
|
||||||
when 'lt'
|
|
||||||
matches_rank = metadata.rank.to_i < query_rank
|
|
||||||
when 'gte'
|
|
||||||
matches_rank = metadata.rank.to_i >= query_rank
|
|
||||||
when 'lte'
|
|
||||||
matches_rank = metadata.rank.to_i <= query_rank
|
|
||||||
when 'eq'
|
|
||||||
matches_rank = metadata.rank.to_i == query_rank
|
|
||||||
end
|
|
||||||
end
|
|
||||||
match = match && matches_rank
|
|
||||||
when :ref, :ref_name
|
|
||||||
match = match && metadata.ref_name =~ r
|
|
||||||
when :reference, :references
|
|
||||||
match = match && metadata.references.any? { |ref| ref =~ r }
|
|
||||||
when :target, :targets
|
|
||||||
match = match && metadata.targets.any? { |target| target =~ r }
|
|
||||||
when :text
|
|
||||||
terms = [metadata.name, metadata.full_name, metadata.description] + metadata.references + metadata.author
|
|
||||||
if metadata.targets
|
|
||||||
terms = terms + metadata.targets
|
|
||||||
end
|
|
||||||
match = match && terms.any? { |term| term =~ r}
|
|
||||||
when :type
|
|
||||||
match = match && (Msf::MODULE_TYPES.any? { |type| value == type and metadata.type == type })
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
match
|
params
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_fields(module_metadata, opts)
|
def get_fields(opts, module_metadata)
|
||||||
selected_fields = {}
|
selected_fields = {}
|
||||||
|
|
||||||
aliases = {
|
aliases = {
|
||||||
|
|
|
@ -10,8 +10,10 @@ module Msf::Modules::Metadata::Search
|
||||||
def find(search_string)
|
def find(search_string)
|
||||||
search_results = []
|
search_results = []
|
||||||
|
|
||||||
|
params = parse_search_string(search_string)
|
||||||
|
|
||||||
get_metadata.each { |module_metadata|
|
get_metadata.each { |module_metadata|
|
||||||
if is_match(search_string, module_metadata)
|
if is_match(params, module_metadata)
|
||||||
search_results << module_metadata
|
search_results << module_metadata
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -19,15 +21,16 @@ module Msf::Modules::Metadata::Search
|
||||||
return search_results
|
return search_results
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Helper method for private `is_match`
|
||||||
|
def matches(params, module_metadata)
|
||||||
|
is_match(params, module_metadata)
|
||||||
|
end
|
||||||
|
|
||||||
#######
|
#######
|
||||||
private
|
private
|
||||||
#######
|
#######
|
||||||
|
|
||||||
def is_match(search_string, module_metadata)
|
def parse_search_string(search_string)
|
||||||
return false if not search_string
|
|
||||||
|
|
||||||
search_string += ' '
|
|
||||||
|
|
||||||
# Split search terms by space, but allow quoted strings
|
# Split search terms by space, but allow quoted strings
|
||||||
terms = search_string.split(/\"/).collect{|t| t.strip==t ? t : t.split(' ')}.flatten
|
terms = search_string.split(/\"/).collect{|t| t.strip==t ? t : t.split(' ')}.flatten
|
||||||
terms.delete('')
|
terms.delete('')
|
||||||
|
@ -37,7 +40,7 @@ module Msf::Modules::Metadata::Search
|
||||||
|
|
||||||
terms.each do |t|
|
terms.each do |t|
|
||||||
f,v = t.split(":", 2)
|
f,v = t.split(":", 2)
|
||||||
if not v
|
unless v
|
||||||
v = f
|
v = f
|
||||||
f = 'text'
|
f = 'text'
|
||||||
end
|
end
|
||||||
|
@ -52,8 +55,13 @@ module Msf::Modules::Metadata::Search
|
||||||
res[f][0] << v
|
res[f][0] << v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
res
|
||||||
|
end
|
||||||
|
|
||||||
k = res
|
def is_match(params, module_metadata)
|
||||||
|
return false if params.empty?
|
||||||
|
|
||||||
|
k = params
|
||||||
|
|
||||||
[0,1].each do |mode|
|
[0,1].each do |mode|
|
||||||
match = false
|
match = false
|
||||||
|
@ -68,6 +76,67 @@ module Msf::Modules::Metadata::Search
|
||||||
r = Regexp.new(Regexp.escape(w), true)
|
r = Regexp.new(Regexp.escape(w), true)
|
||||||
|
|
||||||
case t
|
case t
|
||||||
|
when 'app'
|
||||||
|
match = [t,w] if (w == "server" and module_metadata.is_server)
|
||||||
|
match = [t,w] if (w == "client" and module_metadata.is_client)
|
||||||
|
when 'author', 'authors'
|
||||||
|
match = [t,w] if module_metadata.author.any? { |a| a =~ r }
|
||||||
|
when 'arch'
|
||||||
|
match = [t,w,] if module_metadata.arch =~ r
|
||||||
|
when 'cve'
|
||||||
|
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^cve\-/i and ref =~ r }
|
||||||
|
when 'bid'
|
||||||
|
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^bid\-/i and ref =~ r }
|
||||||
|
when 'edb'
|
||||||
|
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^edb\-/i and ref =~ r }
|
||||||
|
when 'date', 'disclosure_date'
|
||||||
|
match = [t,w] if module_metadata.disclosure_date.to_s =~ r
|
||||||
|
when 'description'
|
||||||
|
match = [t,w] if module_metadata.description =~ r
|
||||||
|
when 'full_name', 'fullname'
|
||||||
|
match = [t,w] if module_metadata.full_name =~ r
|
||||||
|
when 'mod_time'
|
||||||
|
match = [t,w] if module_metadata.mod_time.to_s =~ r
|
||||||
|
when 'name'
|
||||||
|
match = [t,w] if module_metadata.name =~ r
|
||||||
|
when 'os', 'platform'
|
||||||
|
match = [t,w] if module_metadata.platform =~ r or module_metadata.arch =~ r
|
||||||
|
if module_metadata.targets
|
||||||
|
match = [t,w] if module_metadata.targets.any? { |t| t =~ r }
|
||||||
|
end
|
||||||
|
when 'path'
|
||||||
|
match = [t,w] if module_metadata.full_name =~ r
|
||||||
|
when 'port', 'rport'
|
||||||
|
match = [t,w] if module_metadata.rport =~ r
|
||||||
|
when 'rank'
|
||||||
|
# Determine if param was prepended with gt, lt, gte, lte, or eq
|
||||||
|
# Ex: "lte300" should match all ranks <= 300
|
||||||
|
query_rank = w.dup
|
||||||
|
operator = query_rank[0,3].tr('0-9', '')
|
||||||
|
matches_rank = module_metadata.rank == w.to_i
|
||||||
|
unless operator.empty?
|
||||||
|
query_rank.slice! operator
|
||||||
|
query_rank = query_rank.to_i
|
||||||
|
case operator
|
||||||
|
when 'gt'
|
||||||
|
matches_rank = module_metadata.rank.to_i > query_rank
|
||||||
|
when 'lt'
|
||||||
|
matches_rank = module_metadata.rank.to_i < query_rank
|
||||||
|
when 'gte'
|
||||||
|
matches_rank = module_metadata.rank.to_i >= query_rank
|
||||||
|
when 'lte'
|
||||||
|
matches_rank = module_metadata.rank.to_i <= query_rank
|
||||||
|
when 'eq'
|
||||||
|
matches_rank = module_metadata.rank.to_i == query_rank
|
||||||
|
end
|
||||||
|
end
|
||||||
|
match = [t,w] if matches_rank
|
||||||
|
when 'ref', 'ref_name'
|
||||||
|
match = [t,w] if module_metadata.ref_name =~ r
|
||||||
|
when 'reference', 'references'
|
||||||
|
match = [t,w] if module_metadata.references.any? { |ref| ref =~ r }
|
||||||
|
when 'target', 'targets'
|
||||||
|
match = [t,w] if module_metadata.targets.any? { |target| target =~ r }
|
||||||
when 'text'
|
when 'text'
|
||||||
terms = [module_metadata.name, module_metadata.full_name, module_metadata.description] + module_metadata.references + module_metadata.author
|
terms = [module_metadata.name, module_metadata.full_name, module_metadata.description] + module_metadata.references + module_metadata.author
|
||||||
|
|
||||||
|
@ -75,31 +144,8 @@ module Msf::Modules::Metadata::Search
|
||||||
terms = terms + module_metadata.targets
|
terms = terms + module_metadata.targets
|
||||||
end
|
end
|
||||||
match = [t,w] if terms.any? { |x| x =~ r }
|
match = [t,w] if terms.any? { |x| x =~ r }
|
||||||
when 'name'
|
|
||||||
match = [t,w] if module_metadata.name =~ r
|
|
||||||
when 'path'
|
|
||||||
match = [t,w] if module_metadata.full_name =~ r
|
|
||||||
when 'author'
|
|
||||||
match = [t,w] if module_metadata.author.any? { |a| a =~ r }
|
|
||||||
when 'os', 'platform'
|
|
||||||
match = [t,w] if module_metadata.platform =~ r or module_metadata.arch =~ r
|
|
||||||
|
|
||||||
if module_metadata.targets
|
|
||||||
match = [t,w] if module_metadata.targets.any? { |t| t =~ r }
|
|
||||||
end
|
|
||||||
when 'port'
|
|
||||||
match = [t,w] if module_metadata.rport =~ r
|
|
||||||
when 'type'
|
when 'type'
|
||||||
match = [t,w] if Msf::MODULE_TYPES.any? { |modt| w == modt and module_metadata.type == modt }
|
match = [t,w] if Msf::MODULE_TYPES.any? { |modt| w == modt and module_metadata.type == modt }
|
||||||
when 'app'
|
|
||||||
match = [t,w] if (w == "server" and module_metadata.is_server)
|
|
||||||
match = [t,w] if (w == "client" and module_metadata.is_client)
|
|
||||||
when 'cve'
|
|
||||||
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^cve\-/i and ref =~ r }
|
|
||||||
when 'bid'
|
|
||||||
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^bid\-/i and ref =~ r }
|
|
||||||
when 'edb'
|
|
||||||
match = [t,w] if module_metadata.references.any? { |ref| ref =~ /^edb\-/i and ref =~ r }
|
|
||||||
end
|
end
|
||||||
break if match
|
break if match
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue