Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/msf/core/analyze.rb
Views: 11779
class Msf::Analyze12def initialize(framework)3@framework = framework4end56def host(eval_host, payloads: nil)7unless eval_host.vulns8return {}9end1011# Group related vulns12vuln_families = group_vulns(eval_host.vulns)1314# finds all modules that have references matching those found on host vulns with service data15suggested_modules = suggest_modules_for_vulns(eval_host, vuln_families, payloads: payloads)1617{results: suggested_modules}18end1920private2122def group_vulns(vulns)23return [] if vulns.empty?2425vulns = vulns.map do |vuln|26[vuln, Set.new(vuln.refs.map {|r| r.name.upcase})]27end28grouped_vulns = Hash.new2930vulns.each_index do |ii|31vuln, refs = vulns[ii]32grouped_vulns[vuln] ||= [Set.new, Set.new]33grouped_vulns[vuln][0] << vuln34grouped_vulns[vuln][1].merge(refs)3536vulns[(ii+1)..-1].each do |candidate_match, candidate_refs|37# TODO: measure if sorting the refs ahead of time and doing a O(n + m)38# walk here is faster39if candidate_refs.intersect? refs40if grouped_vulns[candidate_match]41# For merging two different transitive sets that overlap, we need42# to merge the individual grouping elements and then use those43# cells inside both the grouping arrays so that all the44# already-visited vulns are rolled into the big new set45grouped_vulns[candidate_match][0] = grouped_vulns[candidate_match][0].merge(grouped_vulns[vuln][0])46grouped_vulns[candidate_match][1] = grouped_vulns[candidate_match][1].merge(grouped_vulns[vuln][1])47grouped_vulns[vuln][0] = grouped_vulns[candidate_match][0]48grouped_vulns[vuln][1] = grouped_vulns[candidate_match][1]49else50# Whoever was initialized first has the canonical set51grouped_vulns[candidate_match] = grouped_vulns[vuln]52end53end54end55end5657vuln_families = grouped_vulns.values58vuln_families.uniq!59vuln_families60end6162def suggest_modules_for_vulns(eval_host, vuln_families, payloads: nil)63mrefs, _mports, _mservs = Msf::Modules::Metadata::Cache.instance.all_exploit_maps64suggested_modules = []6566evaluated_module_targets = Set.new67to_evaluate_with_defaults = Array.new68vuln_families.each do |vulns, refs|69found_modules = mrefs.values_at(*refs).compact.reduce(:+)70next unless found_modules7172services = vulns.map(&:service).compact73found_modules.each do |fnd_mod|74if services.any?75services.each do |svc|76port = svc.port77next if evaluated_module_targets.include?([fnd_mod, port])7879creds = @framework.db.creds(svcs: [svc.name], workspace: eval_host.workspace)80r = Result.new(mod: fnd_mod, host: eval_host, datastore: {'rport': port},81available_creds: creds, payloads: payloads, framework: @framework)82if r.match?83suggested_modules << r.evaluate84end85evaluated_module_targets << [fnd_mod, port]86end87else88# Only have the default port to go off of, at least for this vuln,89# prefer using the service data if available on a different vuln90# entry91port = fnd_mod.rport92to_evaluate_with_defaults << [fnd_mod, port]93end94end95end9697to_evaluate_with_defaults.each do |fnd_mod, port|98next if evaluated_module_targets.include?([fnd_mod, port])99100creds = @framework.db.creds(port: port, workspace: eval_host.workspace) if port101r = Result.new(mod: fnd_mod, host: eval_host, datastore: {'rport': port},102available_creds: creds, payloads: payloads, framework: @framework)103104if r.match?105suggested_modules << r.evaluate106end107evaluated_module_targets << [fnd_mod, port]108end109110suggested_modules111end112end113114115