Skip to content

Commit d2607c7

Browse files
Land #18451, Update creds cracked password to work with remote database
2 parents 5d6b63c + 941c44f commit d2607c7

File tree

1 file changed

+28
-21
lines changed
  • lib/msf/ui/console/command_dispatcher

1 file changed

+28
-21
lines changed

lib/msf/ui/console/command_dispatcher/creds.rb

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ def creds_search(*args)
444444
}
445445

446446
opts[:workspace] = framework.db.workspace
447-
query = framework.db.creds(opts)
447+
cred_cores = framework.db.creds(opts).to_a
448+
cred_cores.sort_by!(&:id)
448449
matched_cred_ids = []
449450
cracked_cred_ids = []
450451

@@ -459,7 +460,7 @@ def creds_search(*args)
459460
tbl = Rex::Text::Table.new(tbl_opts)
460461
end
461462

462-
filtered_query(query, opts, origin_ranges, host_ranges) do |core, service, origin, cracked_password_core|
463+
filter_cred_cores(cred_cores, opts, origin_ranges, host_ranges) do |core, service, origin, cracked_password_core|
463464
matched_cred_ids << core.id
464465
cracked_cred_ids << cracked_password_core.id if cracked_password_core.present?
465466

@@ -550,13 +551,30 @@ def cmd_creds_tabs(str, words)
550551

551552
protected
552553

553-
def filtered_query(query, opts, origin_ranges, host_ranges)
554-
query.each do |core|
555-
# we will not show the cracked password in a seperate row instead we will show in seperate column
556-
# calling `find_by` against this result is a rails direct interaction that may fail in json database mode
557-
if core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword) && query.find_by(id: core.origin.metasploit_credential_core_id).present?
558-
next
559-
end
554+
# @param [Array<Metasploit::Credential::Core>] cores The list of cores to filter
555+
# @param [Hash] opts
556+
# @param [Array<Rex::Socket::RangeWalker>] origin_ranges
557+
# @param [Array<Rex::Socket::RangeWalker>] host_ranges
558+
# @yieldparam [Metasploit::Credential::Core] core
559+
# @yieldparam [Mdm::Service] service
560+
# @yieldparam [Metasploit::Credential::Origin] origin
561+
# @yieldparam [Metasploit::Credential::Origin::CrackedPassword] cracked_password_core
562+
def filter_cred_cores(cores, opts, origin_ranges, host_ranges)
563+
# Some creds may have been cracked that exist outside of the filtered cores list, let's resolve them all to show the cracked value
564+
cores_by_id = cores.each_with_object({}) { |core, hash| hash[core.id] = core }
565+
# Map of any originating core ids that have been cracked; The value is cracked core value
566+
cracked_core_id_to_cracked_value = cores.each_with_object({}) do |core, hash|
567+
next unless core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword)
568+
hash[core.origin.metasploit_credential_core_id] = core
569+
end
570+
571+
cores.each do |core|
572+
# Skip the cracked password if it's planned to be shown on the originating core row in a separate column
573+
is_duplicate_cracked_password_row = core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword) &&
574+
cracked_core_id_to_cracked_value.key?(core.origin.metasploit_credential_core_id) &&
575+
# The core might exist outside of the currently available cores to render
576+
cores_by_id.key?(core.origin.metasploit_credential_core_id)
577+
next if is_duplicate_cracked_password_row
560578

561579
# Exclude non-blank username creds if that's what we're after
562580
if opts[:user] == '' && core.public && !(core.public.username.blank?)
@@ -581,18 +599,7 @@ def filtered_query(query, opts, origin_ranges, host_ranges)
581599
next
582600
end
583601

584-
# this is a direct rails interaction that cannot cross the json db service layer, access of origin objects may be problematic
585-
cracked_password_core = nil
586-
587-
if !core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword) && core.public.cores.count > 1
588-
core.public.cores.each do |potential_cracked_core|
589-
next unless potential_cracked_core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword)
590-
if potential_cracked_core.origin.originating_core == core
591-
cracked_password_core = potential_cracked_core
592-
end
593-
end
594-
end
595-
602+
cracked_password_core = cracked_core_id_to_cracked_value.fetch(core.id, nil)
596603
if core.logins.empty?
597604
service = service_from_origin(core)
598605
next if service.nil? && host_ranges.present? # If we're filtering by login IP and we're here there's no associated login, so skip

0 commit comments

Comments
 (0)