-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix PASSWORD_SPRAY being ignored for LDAP (and potetnially other modules) #19079
Merged
Merged
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
9b1978c
PASSWORD_SPRAY handling
nrathaus 5625493
PASSWORD_SPRAY passing to credentials
nrathaus ec19414
Pass the PASSWORD_SPRAY value
nrathaus c239db5
Revert "PASSWORD_SPRAY handling"
nrathaus b7e0e83
Use yields rather than build an array and sort
nrathaus ebf94ee
Created spec test for password_spray
nrathaus 1f90057
and_return rather than and_yield
nrathaus c09ba17
Change order so that the second is a yield
nrathaus 8526938
Change the order to make the test work with the yield
nrathaus 533a631
Fix suggestions given by cgranleese-r7
nrathaus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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 | ||||||
|
||||||
|
@@ -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 | ||||||
|
@@ -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 | ||||||
# ... | ||||||
cgranleese-r7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
def each_unfiltered_password_first | ||||||
if user_file.present? | ||||||
user_fd = File.open(user_file, 'r:binary') | ||||||
cgranleese-r7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
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)) | ||||||
cgranleese-r7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
# i.e. | ||||||
# username1:password1 | ||||||
# username1:password2 | ||||||
# username1:password3 | ||||||
# ... | ||||||
# username2:password1 | ||||||
# username2:password2 | ||||||
# username2:password3 | ||||||
def each_unfiltered_username_first | ||||||
cgranleese-r7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if pass_file.present? | ||||||
pass_fd = File.open(pass_file, 'r:binary') | ||||||
end | ||||||
|
@@ -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 | ||||||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.