Skip to content

Commit 7dc58d0

Browse files
David MaloneyDavid Maloney
authored andcommitted
make only one each method
made the one true enumerator of credentials for the login_scanner. also covered the wierd http case where it can have a realm key but no default realm.
1 parent a319d52 commit 7dc58d0

File tree

20 files changed

+91
-92
lines changed

20 files changed

+91
-92
lines changed

lib/metasploit/framework/login_scanner/base.rb

Lines changed: 46 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -77,47 +77,39 @@ def attempt_login(credential)
7777
raise NotImplementedError
7878
end
7979

80-
# This method takes a {Metasploit::Framework::Credential} and yields
81-
# one or more {Metasploit::Framework::Credential} objects, adjusted for
82-
# any changes needed around realm. This will add default realms if they are
83-
# needed, adjust realm keys appropriately, and even convert the realm into
84-
# part of the public to try windows-based authentication schemes.
85-
#
86-
# @param [Metasploit::Framework::Credential] the base credential object
87-
# @yieldparam [Metasploit::Framework::Credential] an adjusted credential object
88-
# @raise [ArgumentError] if the credential is invalid
89-
# @return [void]
90-
def each_cred_adjusted_for_realm(credential)
91-
unless credential.kind_of?(Metasploit::Framework::Credential) && credential.valid?
92-
raise ArgumentError, "#{credential.inspect} is not a valid Metasploit::Framework::Credential"
93-
end
9480

95-
if credential.realm.present? && self.class::REALM_KEY.present?
96-
credential.realm_key = self.class::REALM_KEY
97-
yield credential
98-
elsif credential.realm.blank? && self.class::REALM_KEY.present?
99-
credential.realm_key = self.class::REALM_KEY
100-
credential.realm = self.class::DEFAULT_REALM
101-
yield credential
102-
elsif credential.realm.present? && self.class::REALM_KEY.blank?
103-
second_cred = credential.dup
104-
# Strip the realm off here, as we don't want it
105-
credential.realm = nil
106-
credential.realm_key = nil
107-
yield credential
108-
# Some services can take a domain in the username like this even though
109-
# they do not explicitly take a domain as part of the protocol.
110-
second_cred.public = "#{second_cred.realm}\\#{second_cred.public}"
111-
second_cred.realm = nil
112-
second_cred.realm_key = nil
113-
yield second_cred
114-
else
115-
# Strip any realm off here, as we don't want it
116-
credential.realm = nil
117-
credential.realm_key = nil
118-
yield credential
81+
def each_credential
82+
cred_details.each do |raw_cred|
83+
# This could be a Credential object, or a Credential Core, or an Attempt object
84+
# so make sure that whatever it is, we end up with a Credential.
85+
credential = raw_cred.to_credential
86+
87+
if credential.realm.present? && self.class::REALM_KEY.present?
88+
credential.realm_key = self.class::REALM_KEY
89+
yield credential
90+
elsif credential.realm.blank? && self.class::REALM_KEY.present? && self.class::DEFAULT_REALM.present?
91+
credential.realm_key = self.class::REALM_KEY
92+
credential.realm = self.class::DEFAULT_REALM
93+
yield credential
94+
elsif credential.realm.present? && self.class::REALM_KEY.blank?
95+
second_cred = credential.dup
96+
# Strip the realm off here, as we don't want it
97+
credential.realm = nil
98+
credential.realm_key = nil
99+
yield credential
100+
# Some services can take a domain in the username like this even though
101+
# they do not explicitly take a domain as part of the protocol.
102+
second_cred.public = "#{second_cred.realm}\\#{second_cred.public}"
103+
second_cred.realm = nil
104+
second_cred.realm_key = nil
105+
yield second_cred
106+
else
107+
# Strip any realm off here, as we don't want it
108+
credential.realm = nil
109+
credential.realm_key = nil
110+
yield credential
111+
end
119112
end
120-
121113
end
122114

123115
# Attempt to login with every {Credential credential} in
@@ -134,25 +126,21 @@ def scan!
134126
consecutive_error_count = 0
135127
total_error_count = 0
136128

137-
cred_details.each do |raw_credential|
138-
unadjusted_credential = raw_credential.to_credential
139-
# Do some adjusting for Realms in here
140-
each_cred_adjusted_for_realm(unadjusted_credential) do |credential|
141-
result = attempt_login(credential)
142-
result.freeze
143-
144-
yield result if block_given?
145-
146-
if result.success?
147-
consecutive_error_count = 0
148-
return nil if stop_on_success
149-
else
150-
if result.status == :connection_error
151-
consecutive_error_count += 1
152-
total_error_count += 1
153-
return nil if consecutive_error_count >= 3
154-
return nil if total_error_count >= 10
155-
end
129+
each_credential do |credential|
130+
result = attempt_login(credential)
131+
result.freeze
132+
133+
yield result if block_given?
134+
135+
if result.success?
136+
consecutive_error_count = 0
137+
break if stop_on_success
138+
else
139+
if result.status == :connection_error
140+
consecutive_error_count += 1
141+
total_error_count += 1
142+
break if consecutive_error_count >= 3
143+
break if total_error_count >= 10
156144
end
157145
end
158146
end

lib/metasploit/framework/login_scanner/http.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ class HTTP
1212
include Metasploit::Framework::LoginScanner::Base
1313
include Metasploit::Framework::LoginScanner::RexSocket
1414

15+
DEFAULT_REALM = nil
1516
DEFAULT_PORT = 80
1617
DEFAULT_SSL_PORT = 443
1718
LIKELY_PORTS = [ 80, 443, 8000, 8080 ]
1819
LIKELY_SERVICE_NAMES = [ 'http', 'https' ]
1920
PRIVATE_TYPES = [ :password ]
20-
REALM_KEY = nil
21+
REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
2122

2223
# @!attribute uri
2324
# @return [String] The path and query string on the server to

lib/metasploit/framework/login_scanner/smb.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SMB
2222
LIKELY_PORTS = [ 139, 445 ]
2323
LIKELY_SERVICE_NAMES = [ "smb" ]
2424
PRIVATE_TYPES = [ :password, :ntlm_hash ]
25-
REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
25+
REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
2626

2727
module StatusCodes
2828
CORRECT_CREDENTIAL_STATUS_CODES = [

spec/lib/metasploit/framework/login_scanner/afp_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
subject(:scanner) { described_class.new }
88

9-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false
9+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false, false
1010
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
1111

1212
it { should respond_to :login_timeout }

spec/lib/metasploit/framework/login_scanner/axis2_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
describe Metasploit::Framework::LoginScanner::Axis2 do
66

7-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false
7+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true, false
88
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
99
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
1010

spec/lib/metasploit/framework/login_scanner/db2_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
}
1010
subject(:login_scanner) { described_class.new }
1111

12-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true
12+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true, true
1313
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
1414

1515
context '#attempt_login' do

spec/lib/metasploit/framework/login_scanner/ftp_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
described_class.new
4646
}
4747

48-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false
48+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false, false
4949
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
5050

5151

spec/lib/metasploit/framework/login_scanner/http_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
describe Metasploit::Framework::LoginScanner::HTTP do
66

7-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false
7+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true, false
88
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
99
it_behaves_like 'Metasploit::Framework::LoginScanner::HTTP'
1010

spec/lib/metasploit/framework/login_scanner/mssql_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
subject(:login_scanner) { described_class.new }
3434

35-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true
35+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', true, true
3636
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
3737
it_behaves_like 'Metasploit::Framework::LoginScanner::NTLM'
3838

spec/lib/metasploit/framework/login_scanner/mysql_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
subject(:login_scanner) { described_class.new }
3232

33-
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false
33+
it_behaves_like 'Metasploit::Framework::LoginScanner::Base', false, false
3434
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
3535

3636
context '#attempt_login' do

0 commit comments

Comments
 (0)