Skip to content

Commit bdbb26b

Browse files
committed
Land rapid7#4540, resolves rapid7#4532, honour DB_ALL_* options
2 parents 361057c + 702511d commit bdbb26b

File tree

2 files changed

+124
-13
lines changed

2 files changed

+124
-13
lines changed

lib/metasploit/framework/credential_collection.rb

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
class Metasploit::Framework::CredentialCollection
44

5+
# @!attribute additional_privates
6+
# Additional privates to be combined
7+
#
8+
# @return [Array<String>]
9+
attr_accessor :additional_privates
10+
11+
# @!attribute additional_publics
12+
# Additional public to be combined
13+
#
14+
# @return [Array<String>]
15+
attr_accessor :additional_publics
16+
517
# @!attribute blank_passwords
618
# Whether each username should be tried with a blank password
719
# @return [Boolean]
@@ -59,7 +71,27 @@ def initialize(opts = {})
5971
opts.each do |attribute, value|
6072
public_send("#{attribute}=", value)
6173
end
62-
self.prepended_creds ||= []
74+
self.prepended_creds ||= []
75+
self.additional_privates ||= []
76+
self.additional_publics ||= []
77+
end
78+
79+
# Adds a string as an addition private credential
80+
# to be combined in the collection.
81+
#
82+
# @param [String] :private_str the string to use as a private
83+
# @return [void]
84+
def add_private(private_str='')
85+
additional_privates << private_str
86+
end
87+
88+
# Adds a string as an addition public credential
89+
# to be combined in the collection.
90+
#
91+
# @param [String] :public_str the string to use as a public
92+
# @return [void]
93+
def add_public(public_str='')
94+
additional_publics << public_str
6395
end
6496

6597
# Add {Credential credentials} that will be yielded by {#each}
@@ -101,6 +133,9 @@ def each
101133
end
102134
pass_fd.seek(0)
103135
end
136+
additional_privates.each do |add_private|
137+
yield Metasploit::Framework::Credential.new(public: username, private: add_private, realm: realm, private_type: private_type(add_private))
138+
end
104139
end
105140

106141
if user_file.present?
@@ -123,6 +158,9 @@ def each
123158
end
124159
pass_fd.seek(0)
125160
end
161+
additional_privates.each do |add_private|
162+
yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))
163+
end
126164
end
127165
end
128166
end
@@ -141,6 +179,28 @@ def each
141179
end
142180
end
143181

182+
additional_publics.each do |add_public|
183+
if password.present?
184+
yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )
185+
end
186+
if user_as_pass
187+
yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)
188+
end
189+
if blank_passwords
190+
yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)
191+
end
192+
if pass_fd
193+
pass_fd.each_line do |pass_from_file|
194+
pass_from_file.chomp!
195+
yield Metasploit::Framework::Credential.new(public: add_public, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))
196+
end
197+
pass_fd.seek(0)
198+
end
199+
additional_privates.each do |add_private|
200+
yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
201+
end
202+
end
203+
144204
ensure
145205
pass_fd.close if pass_fd && !pass_fd.closed?
146206
end

lib/msf/core/auxiliary/auth_brute.rb

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,57 @@ def setup
4949
@@max_per_service = nil
5050
end
5151

52+
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
53+
# a private type of 'ntlm_hash'
54+
#
55+
# @yieldparam [Metasploit::Credential::Core]
56+
def each_ntlm_cred
57+
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
58+
creds.each do |cred|
59+
yield cred
60+
end
61+
end
62+
63+
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
64+
# a private type of 'password'
65+
#
66+
# @yieldparam [Metasploit::Credential::Core]
67+
def each_password_cred
68+
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
69+
creds.each do |cred|
70+
yield cred
71+
end
72+
end
73+
74+
# Yields each {Metasploit::Credential::Core} in the {Mdm::Workspace} with
75+
# a private type of 'ssh_key'
76+
#
77+
# @yieldparam [Metasploit::Credential::Core]
78+
def each_ssh_cred
79+
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
80+
creds.each do |cred|
81+
yield cred
82+
end
83+
end
84+
85+
# Checks whether we should be adding creds from the DB to a CredCollection
86+
#
87+
# @return [TrueClass] if any of the datastore options for db creds are selected and the db is active
88+
# @return [FalseClass] if none of the datastore options are selected OR the db is not active
89+
def prepend_db_creds?
90+
(datastore['DB_ALL_CREDS'] || datastore['DB_ALL_PASS'] || datastore['DB_ALL_USERS']) && framework.db.active
91+
end
92+
5293
# This method takes a {Metasploit::Framework::CredentialCollection} and prepends existing NTLMHashes
5394
# from the database. This allows the users to use the DB_ALL_CREDS option.
5495
#
5596
# @param cred_collection [Metasploit::Framework::CredentialCollection]
5697
# the credential collection to add to
5798
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
5899
def prepend_db_hashes(cred_collection)
59-
if datastore['DB_ALL_CREDS'] && framework.db.active
60-
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::NTLMHash' }, workspace_id: myworkspace.id)
61-
creds.each do |cred|
62-
cred_collection.prepend_cred(cred.to_credential)
100+
if prepend_db_creds?
101+
each_ntlm_cred do |cred|
102+
process_cred_for_collection(cred_collection,cred)
63103
end
64104
end
65105
cred_collection
@@ -72,10 +112,9 @@ def prepend_db_hashes(cred_collection)
72112
# the credential collection to add to
73113
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
74114
def prepend_db_keys(cred_collection)
75-
if datastore['DB_ALL_CREDS'] && framework.db.active
76-
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::SSHKey' }, workspace_id: myworkspace.id)
77-
creds.each do |cred|
78-
cred_collection.prepend_cred(cred.to_credential)
115+
if prepend_db_creds?
116+
each_ssh_cred do |cred|
117+
process_cred_for_collection(cred_collection,cred)
79118
end
80119
end
81120
cred_collection
@@ -88,15 +127,27 @@ def prepend_db_keys(cred_collection)
88127
# the credential collection to add to
89128
# @return [Metasploit::Framework::CredentialCollection] the modified Credentialcollection
90129
def prepend_db_passwords(cred_collection)
91-
if datastore['DB_ALL_CREDS'] && framework.db.active
92-
creds = Metasploit::Credential::Core.joins(:private).where(metasploit_credential_privates: { type: 'Metasploit::Credential::Password' }, workspace_id: myworkspace.id)
93-
creds.each do |cred|
94-
cred_collection.prepend_cred(cred.to_credential)
130+
if prepend_db_creds?
131+
each_password_cred do |cred|
132+
process_cred_for_collection(cred_collection,cred)
95133
end
96134
end
97135
cred_collection
98136
end
99137

138+
# Takes a {Metasploit::Credential::Core} and converts it into a
139+
# {Metasploit::Framework::Credential} and processes it into the
140+
# {Metasploit::Framework::CredentialCollection} as dictated by the
141+
# selected datastore options.
142+
#
143+
# @param [Metasploit::Framework::CredentialCollection] the credential collection to add to
144+
# @param [Metasploit::Credential::Core] the Credential Core to process
145+
def process_cred_for_collection(cred_collection, cred)
146+
msf_cred = cred.to_credential
147+
cred_collection.prepend_cred(msf_cred) if datastore['DB_ALL_CREDS']
148+
cred_collection.add_private(msf_cred.private) if datastore['DB_ALL_PASS']
149+
cred_collection.add_public(msf_cred.public) if datastore['DB_ALL_USERS']
150+
end
100151

101152

102153
# Checks all three files for usernames and passwords, and combines them into

0 commit comments

Comments
 (0)