Skip to content

Commit

Permalink
Use yields rather than build an array and sort
Browse files Browse the repository at this point in the history
  • Loading branch information
nrathaus committed Apr 12, 2024
1 parent c239db5 commit b7e0e83
Showing 1 changed file with 130 additions and 10 deletions.
140 changes: 130 additions & 10 deletions lib/metasploit/framework/credential_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,24 @@ def prepend_cred(cred)
self
end

# Combines all the provided credential sources into a stream of {Credential}
# objects, yielding them one at a time
#
# @yieldparam credential [Metasploit::Framework::Credential]
# @return [void]
def each_filtered
each_unfiltered do |credential|
next unless self.filter.nil? || self.filter.call(credential)
if password_spray
each_unfiltered_password_first do |credential|
next unless self.filter.nil? || self.filter.call(credential)

yield credential
end
else
each_unfiltered_username_first do |credential|
next unless self.filter.nil? || self.filter.call(credential)

yield credential
yield credential
end
end
end

Expand Down Expand Up @@ -164,6 +177,7 @@ def private_type(private)
end

class CredentialCollection < PrivateCredentialCollection
attr_accessor :password_spray

# @!attribute additional_publics
# Additional public values that should be tried
Expand Down Expand Up @@ -219,12 +233,119 @@ def add_public(public_str='')
additional_publics << public_str
end

# Combines all the provided credential sources into a stream of {Credential}
# objects, yielding them one at a time
#
# @yieldparam credential [Metasploit::Framework::Credential]
# @return [void]
def each_unfiltered
# When password spraying is enabled, do first passwords then userames
# i.e.
# username1:password1
# username2:password1
# username3:password1
# ...
# username1:password2
# username2:password2
# username3:password2
# ...
def each_unfiltered_password_first
if user_file.present?
user_fd = File.open(user_file, 'r:binary')
end

prepended_creds.each { |c| yield c }

if anonymous_login
yield Metasploit::Framework::Credential.new(public: '', private: '', realm: realm, private_type: :password)
end

if password.present?
if nil_passwords
yield Metasploit::Framework::Credential.new(public: username, private: nil, realm: realm, private_type: :password)
end
if username.present?
yield Metasploit::Framework::Credential.new(public: username, private: password, realm: realm, private_type: private_type(password))
end
if user_as_pass
yield Metasploit::Framework::Credential.new(public: username, private: username, realm: realm, private_type: :password)
end
if blank_passwords
yield Metasploit::Framework::Credential.new(public: username, private: "", realm: realm, private_type: :password)
end
if user_fd
user_fd.each_line do |user_from_file|
user_from_file.chomp!
yield Metasploit::Framework::Credential.new(public: user_from_file, private: password, realm: realm, private_type: private_type(pass_from_file))
end
user_fd.seek(0)
end
end

if pass_file.present?
File.open(pass_file, 'r:binary') do |pass_fd|
pass_fd.each_line do |pass_from_file|
pass_from_file.chomp!
if user_as_pass
yield Metasploit::Framework::Credential.new(public: pass_from_file, private: pass_from_file, realm: realm, private_type: :password)
end
if user_fd
user_fd.each_line do |user_from_file|
user_from_file.chomp!
yield Metasploit::Framework::Credential.new(public: user_from_file, private: pass_from_file, realm: realm, private_type: private_type(pass_from_file))
end
user_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: user_from_file, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
end
end

if userpass_file.present?
File.open(userpass_file, 'r:binary') do |userpass_fd|
userpass_fd.each_line do |line|
user, pass = line.split(" ", 2)
if pass.blank?
pass = ''
else
pass.chomp!
end
yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm)
end
end
end

additional_publics.each do |add_public|
if password.present?
yield Metasploit::Framework::Credential.new(public: add_public, private: password, realm: realm, private_type: private_type(password) )
end
if user_as_pass
yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: :password)
end
if blank_passwords
yield Metasploit::Framework::Credential.new(public: add_public, private: "", realm: realm, private_type: :password)
end
if user_fd
user_fd.each_line do |user_from_file|
user_from_file.chomp!
yield Metasploit::Framework::Credential.new(public: add_public, private: user_from_file, realm: realm, private_type: private_type(user_from_file))
end
user_fd.seek(0)
end
additional_privates.each do |add_private|
yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
end
end
ensure
user_fd.close if user_fd && !user_fd.closed?
end

# When password spraying is not enabled, do first usersnames then passwords
# i.e.
# username1:password1
# username1:password2
# username1:password3
# ...
# username2:password1
# username2:password2
# username2:password3
def each_unfiltered_username_first
if pass_file.present?
pass_fd = File.open(pass_file, 'r:binary')
end
Expand Down Expand Up @@ -325,7 +446,6 @@ def each_unfiltered
yield Metasploit::Framework::Credential.new(public: add_public, private: add_private, realm: realm, private_type: private_type(add_private))
end
end

ensure
pass_fd.close if pass_fd && !pass_fd.closed?
end
Expand Down

0 comments on commit b7e0e83

Please sign in to comment.