Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d0d3903
commit 7b2c625
Showing
6 changed files
with
225 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
module Msf::Ui::Console::CommandDispatcher::Analyze | ||
|
||
def cmd_analyze(*args) | ||
unless active? | ||
print_error "Not currently connected to a data service for analysis." | ||
return [] | ||
end | ||
|
||
host_ranges = [] | ||
|
||
while (arg = args.shift) | ||
case arg | ||
when '-h','help' | ||
cmd_analyze_help | ||
return | ||
else | ||
(arg_host_range(arg, host_ranges)) | ||
end | ||
end | ||
|
||
host_ranges.push(nil) if host_ranges.empty? | ||
|
||
host_ids = [] | ||
suggested_modules = {} | ||
each_host_range_chunk(host_ranges) do |host_search| | ||
break if !host_search.nil? && host_search.empty? | ||
eval_hosts_ids = framework.db.hosts(address: host_search).map(&:id) | ||
if eval_hosts_ids | ||
eval_hosts_ids.each do |eval_id| | ||
host_ids.push(eval_id) | ||
end | ||
end | ||
end | ||
|
||
if host_ids.empty? | ||
print_status("No existing hosts stored to analyze.") | ||
else | ||
|
||
host_ids.each do |id| | ||
eval_host = framework.db.hosts(id: id).first | ||
next unless eval_host | ||
print_status("Analyzing #{eval_host.address}...") | ||
unless eval_host.vulns | ||
print_status("No suggestions for #{eval_host.address}.") | ||
next | ||
end | ||
|
||
reported_module = false | ||
host_result = framework.analyze.host(eval_host) | ||
found_modules = host_result[:modules] | ||
found_modules.each do |fnd_mod| | ||
print_status(fnd_mod.full_name) | ||
reported_module = true | ||
end | ||
|
||
suggested_modules[eval_host.address] = found_modules | ||
|
||
print_status("No suggestions for #{eval_host.address}.") unless reported_module | ||
end | ||
end | ||
suggested_modules | ||
end | ||
|
||
|
||
def cmd_analyze_help | ||
print_line "Usage: analyze [addr1 addr2 ...]" | ||
print_line | ||
end | ||
|
||
end |