Skip to content

Commit fc8bb54

Browse files
committed
Land rapid7#3330 check admin in smb_login
2 parents 121ab76 + 5fe8814 commit fc8bb54

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

modules/auxiliary/scanner/smb/smb_login.rb

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ def initialize
3232
'Author' =>
3333
[
3434
'tebo <tebo [at] attackresearch [dot] com>', # Original
35-
'Ben Campbell' # Refactoring
35+
'Ben Campbell', # Refactoring
36+
'Brandon McCann "zeknox" <bmccann [at] accuvant.com>', # admin check
37+
'Tom Sellers <tom <at> fadedcode.net>' # admin check/bug fix
3638
],
3739
'References' =>
3840
[
@@ -69,6 +71,7 @@ def initialize
6971
OptString.new('SMBPass', [ false, "SMB Password" ]),
7072
OptString.new('SMBUser', [ false, "SMB Username" ]),
7173
OptString.new('SMBDomain', [ false, "SMB Domain", '']),
74+
OptBool.new('CHECK_ADMIN', [ false, "Check for Admin rights", false]),
7275
OptBool.new('PRESERVE_DOMAINS', [ false, "Respect a username that contains a domain name.", true]),
7376
OptBool.new('RECORD_GUEST', [ false, "Record guest-privileged random logins to the database", false])
7477
], self.class)
@@ -124,6 +127,25 @@ def check_login_status(domain, user, pass)
124127
# Windows SMB will return an error code during Session Setup, but nix Samba requires a Tree Connect:
125128
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
126129
status_code = 'STATUS_SUCCESS'
130+
131+
if datastore['CHECK_ADMIN']
132+
status_code = :not_admin
133+
# Drop the existing connection to IPC$ in order to connect to admin$
134+
simple.disconnect("\\\\#{datastore['RHOST']}\\IPC$")
135+
begin
136+
simple.connect("\\\\#{datastore['RHOST']}\\admin$")
137+
status_code = :admin_access
138+
simple.disconnect("\\\\#{datastore['RHOST']}\\admin$")
139+
rescue
140+
status_code = :not_admin
141+
ensure
142+
begin
143+
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
144+
rescue ::Rex::Proto::SMB::Exceptions::NoReply
145+
end
146+
end
147+
end
148+
127149
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
128150
status_code = e.get_error(e.error_code)
129151
rescue ::Rex::Proto::SMB::Exceptions::LoginError => e
@@ -187,7 +209,16 @@ def accepts_bogus_domains?(user, pass, rhost)
187209
end
188210

189211
def valid_credentials?(status)
190-
return (status == "STATUS_SUCCESS" || @correct_credentials_status_codes.include?(status))
212+
213+
case status
214+
when 'STATUS_SUCCESS', :admin_access, :not_admin
215+
return true
216+
when *@correct_credentials_status_codes
217+
return true
218+
else
219+
return false
220+
end
221+
191222
end
192223

193224
def try_user_pass(domain, user, pass)
@@ -214,7 +245,7 @@ def try_user_pass(domain, user, pass)
214245
output_message << " (#{smb_peer_os}) #{user} : #{pass} [#{status}]".gsub('%', '%%')
215246

216247
case status
217-
when 'STATUS_SUCCESS'
248+
when 'STATUS_SUCCESS', :admin_access, :not_admin
218249
# Auth user indicates if the login was as a guest or not
219250
if(simple.client.auth_user)
220251
print_good(output_message % "SUCCESSFUL LOGIN")
@@ -275,7 +306,7 @@ def note_creds(domain,user,pass,reason)
275306
def report_creds(domain,user,pass,active)
276307
login_name = ""
277308

278-
if accepts_bogus_domains?(user,pass,rhost)
309+
if accepts_bogus_domains?(user,pass,rhost) || domain.blank?
279310
login_name = user
280311
else
281312
login_name = "#{domain}\\#{user}"

0 commit comments

Comments
 (0)