90 lines
3.3 KiB
Ruby
90 lines
3.3 KiB
Ruby
class Msf::Analyze
|
|
|
|
def initialize(framework)
|
|
@framework = framework
|
|
end
|
|
|
|
def host(eval_host)
|
|
suggested_modules = {}
|
|
|
|
mrefs, _mports, _mservs = Msf::Modules::Metadata::Cache.instance.all_remote_exploit_maps
|
|
|
|
unless eval_host.vulns
|
|
return {}
|
|
end
|
|
|
|
vuln_refs = []
|
|
eval_host.vulns.each do |vuln|
|
|
next if vuln.service.nil?
|
|
vuln_refs.push(*vuln.refs)
|
|
end
|
|
|
|
# finds all modules that have references matching those found on host vulns with service data
|
|
found_modules = mrefs.values_at(*(vuln_refs.map { |x| x.name.upcase } & mrefs.keys)).map { |x| x.values }.flatten.uniq
|
|
found_modules.each do |fnd_mod|
|
|
# next if exploit_filter_by_service(fnd_mod, vuln.service)
|
|
next unless exploit_matches_host_os(fnd_mod, eval_host)
|
|
end
|
|
|
|
suggested_modules[:modules] = found_modules
|
|
|
|
suggested_modules
|
|
end
|
|
|
|
|
|
private
|
|
|
|
# Tests for various service conditions by comparing the module's full_name (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)
|
|
|
|
# Filter out IIS exploits for non-Microsoft services
|
|
return true if (mod.full_name =~ /\/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)
|
|
|
|
false
|
|
end
|
|
|
|
# Determines if an exploit (mod, an instantiated module) is suitable for the host (host)
|
|
# defined operating system. Returns true if the host.os isn't defined, if the module's target
|
|
# OS isn't defined, if the module's OS is "unix" and the host's OS is not "windows," or
|
|
# if the module's target is "php." Or, of course, in the event the host.os actually matches.
|
|
# This is a fail-open gate; if there's a doubt, assume the module will work on this target.
|
|
def exploit_matches_host_os(mod, host)
|
|
hos = host.os_name
|
|
return true if hos.nil? || hos.empty?
|
|
|
|
set = mod.platform.split(',').map{ |x| x.downcase }
|
|
return true if set.empty?
|
|
|
|
# Special cases
|
|
return true if set.include?("unix") and hos !~ /windows/i
|
|
|
|
if set.include?("unix")
|
|
# Skip archaic old HPUX bugs if we have a solid match against another OS
|
|
return false if set.include?("hpux") and mod.refname.index("hpux") and hos =~ /linux|irix|solaris|aix|bsd/i
|
|
# Skip AIX bugs if we have a solid match against another OS
|
|
return false if set.include?("aix") and mod.refname.index("aix") and hos =~ /linux|irix|solaris|hpux|bsd/i
|
|
# Skip IRIX bugs if we have a solid match against another OS
|
|
return false if set.include?("irix") and mod.refname.index("irix") and hos =~ /linux|solaris|hpux|aix|bsd/i
|
|
end
|
|
|
|
return true if set.include?("php")
|
|
|
|
set.each do |mos|
|
|
return true if hos.downcase.index(mos)
|
|
end
|
|
|
|
false
|
|
end
|
|
end
|