Skip to content

Commit

Permalink
Land #17689, adding a new column cracked password in creds command to…
Browse files Browse the repository at this point in the history
… show cracked passwords
  • Loading branch information
adfoster-r7 committed Oct 13, 2023
2 parents 44e5a93 + 87582ee commit bb19151
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 27 deletions.
35 changes: 28 additions & 7 deletions lib/msf/ui/console/command_dispatcher/creds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ def creds_search(*args)
set_rhosts = false
truncate = true

cred_table_columns = [ 'host', 'origin' , 'service', 'public', 'private', 'realm', 'private_type', 'JtR Format' ]
cred_table_columns = [ 'host', 'origin' , 'service', 'public', 'private', 'realm', 'private_type', 'JtR Format', 'cracked_password' ]
delete_count = 0
search_term = nil

Expand Down Expand Up @@ -446,6 +446,7 @@ def creds_search(*args)
opts[:workspace] = framework.db.workspace
query = framework.db.creds(opts)
matched_cred_ids = []
cracked_cred_ids = []

if output_file&.ends_with?('.hcat')
output_file = ::File.open(output_file, 'wb')
Expand All @@ -458,8 +459,9 @@ def creds_search(*args)
tbl = Rex::Text::Table.new(tbl_opts)
end

filtered_query(query, opts, origin_ranges, host_ranges) do |core, service, origin|
filtered_query(query, opts, origin_ranges, host_ranges) do |core, service, origin, cracked_password_core|
matched_cred_ids << core.id
cracked_cred_ids << cracked_password_core.id if cracked_password_core.present?

if output_file && output_formatter
formatted = output_formatter.call(core)
Expand Down Expand Up @@ -493,7 +495,7 @@ def creds_search(*args)
rhosts << host unless host.blank?
service_info = build_service_info(service)
end

cracked_password_val = cracked_password_core&.private&.data.to_s
tbl << [
host,
origin,
Expand All @@ -502,7 +504,8 @@ def creds_search(*args)
private_val,
realm_val,
human_val, #private type
jtr_val
jtr_val,
cracked_password_val
]
end
end
Expand All @@ -516,7 +519,7 @@ def creds_search(*args)
end

if mode == :delete
result = framework.db.delete_credentials(ids: matched_cred_ids.uniq)
result = framework.db.delete_credentials(ids: matched_cred_ids.concat(cracked_cred_ids).uniq)
delete_count = result.size
end

Expand Down Expand Up @@ -549,6 +552,12 @@ def cmd_creds_tabs(str, words)

def filtered_query(query, opts, origin_ranges, host_ranges)
query.each do |core|
# we will not show the cracked password in a seperate row instead we will show in seperate column
# calling `find_by` against this result is a rails direct interaction that may fail in json database mode
if core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword) && query.find_by(id: core.origin.metasploit_credential_core_id).present?
next
end

# Exclude non-blank username creds if that's what we're after
if opts[:user] == '' && core.public && !(core.public.username.blank?)
next
Expand All @@ -572,11 +581,23 @@ def filtered_query(query, opts, origin_ranges, host_ranges)
next
end

# this is a direct rails interaction that cannot cross the json db service layer, access of origin objects may be problematic
cracked_password_core = nil

if !core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword) && core.public.cores.count > 1
core.public.cores.each do |potential_cracked_core|
next unless potential_cracked_core.origin.kind_of?(Metasploit::Credential::Origin::CrackedPassword)
if potential_cracked_core.origin.originating_core == core
cracked_password_core = potential_cracked_core
end
end
end

if core.logins.empty?
service = service_from_origin(core)
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

yield core, service, origin
yield core, service, origin, cracked_password_core
else
core.logins.each do |login|
service = framework.db.services(id: login.service_id).first
Expand All @@ -588,7 +609,7 @@ def filtered_query(query, opts, origin_ranges, host_ranges)
next
end

yield core, service, origin
yield core, service, origin, cracked_password_core
end
end
end
Expand Down
102 changes: 82 additions & 20 deletions spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------',
' thisuser thispass Password '
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------',
' thisuser thispass Password '
])
end

Expand All @@ -83,8 +83,8 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------',
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------',
' thisuser thispass Password '
])
end
Expand All @@ -96,9 +96,9 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------',
' nonblank_pass Password '
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------',
' nonblank_pass Password '
])
end
end
Expand All @@ -109,9 +109,9 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------',
' nonblank_user Password '
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------',
' nonblank_user Password '
])
end
end
Expand All @@ -125,8 +125,8 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------'
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------'
])
end
end
Expand All @@ -137,8 +137,45 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------'
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------'
])
end
end
context 'showing new column of cracked_password for all the cracked passwords' do
it 'should show the cracked password in the new column named cracked_passwords' do
common_public = FactoryBot.create(:metasploit_credential_username, username: "this_username")
core = FactoryBot.create(:metasploit_credential_core,
origin: FactoryBot.create(:metasploit_credential_origin_import),
private: FactoryBot.create(:metasploit_credential_nonreplayable_hash, data: "some_hash"),
public: common_public,
realm: nil,
workspace: framework.db.workspace)
cracked_core = FactoryBot.create(:metasploit_credential_core,
origin: Metasploit::Credential::Origin::CrackedPassword.create!(metasploit_credential_core_id: core.id),
private: FactoryBot.create(:metasploit_credential_password, data: "this_cracked_password"),
public: common_public,
realm: nil,
workspace: framework.db.workspace)
creds.cmd_creds('-u', 'this_username')
expect(@output).to eq([
"Credentials",
"===========",
"",
"host origin service public private realm private_type JtR Format cracked_password",
"---- ------ ------- ------ ------- ----- ------------ ---------- ----------------",
" this_username some_hash Nonreplayable hash this_cracked_password"
])
end
it "should show the user given passwords on private column instead of cracked_password column" do
creds.cmd_creds('-u', 'thisuser')
expect(@output).to eq([
"Credentials",
"===========",
"",
"host origin service public private realm private_type JtR Format cracked_password",
"---- ------ ------- ------ ------- ----- ------------ ---------- ----------------",
" thisuser thispass Password "
])
end
end
Expand Down Expand Up @@ -206,11 +243,36 @@
'Credentials',
'===========',
'',
'host origin service public private realm private_type JtR Format',
'---- ------ ------- ------ ------- ----- ------------ ----------',
' thisuser thispass Password '
'host origin service public private realm private_type JtR Format cracked_password',
'---- ------ ------- ------ ------- ----- ------------ ---------- ----------------',
' thisuser thispass Password '
])
end
it 'should show all the cores whose private is either password or the private is cracked password' do
common_public = FactoryBot.create(:metasploit_credential_username, username: "this_username")
core = FactoryBot.create(:metasploit_credential_core,
origin: FactoryBot.create(:metasploit_credential_origin_import),
private: FactoryBot.create(:metasploit_credential_nonreplayable_hash, data: "some_hash"),
public: common_public,
realm: nil,
workspace: framework.db.workspace)
cracked_core = FactoryBot.create(:metasploit_credential_core,
origin: Metasploit::Credential::Origin::CrackedPassword.create!(metasploit_credential_core_id: core.id),
private: FactoryBot.create(:metasploit_credential_password, data: "this_cracked_password"),
public: common_public,
realm: nil,
workspace: framework.db.workspace)
creds.cmd_creds('-t', 'password')
expect(@output).to eq([
"Credentials",
"===========",
"",
"host origin service public private realm private_type JtR Format cracked_password",
"---- ------ ------- ------ ------- ----- ------------ ---------- ----------------",
" thisuser thispass Password ",
" this_username this_cracked_password Password "
])
end
end

context 'ntlm' do
Expand All @@ -223,8 +285,8 @@
'Credentials',
'===========',
'',
'host service public private realm private_type JtR Format',
'---- ------- ------ ------- ----- ------------ ----------',
'host service public private realm private_type JtR Format cracked_password',
'---- ------- ------ ------- ----- ------------ ---------- ----------------',
" thisuser #{ntlm_hash} NTLM hash"
]
end
Expand Down

0 comments on commit bb19151

Please sign in to comment.