#2257·impacket

SMB3.kerberosLogin(mutualAuth=True) uses the full AP-REP subkey as `Session.SessionKey` instead of its first 16 bytes (breaks AES-256 encrypted sessions)

Author: 0xRyuzak1Created Aug 12, 2026Updated Aug 12, 2026
Labelsin review

SMB3.kerberosLogin(mutualAuth=True) uses the full AP-REP subkey as Session.SessionKey instead of its first 16 bytes (breaks AES-256 encrypted sessions)

Description

In impacket/smb3.py, SMB3.kerberosLogin() with mutualAuth=True sets Session.SessionKey to the entire AP-REP sub-session key returned by the server. Per [MS-SMB2] §3.2.5.3, Session.SessionKey MUST be the first 16 bytes of the key obtained from the GSS context. The sibling (non-mutual) branch a few lines below already does this correctly with [:16].

For an AES-256 service ticket the sub-session key is 32 bytes, so Session.SessionKey becomes 32 bytes instead of 16. All SMB3 signing/encryption keys are then derived (KDF_CounterMode) from the wrong input, and against a server that requires SMB signing/encryption the session fails immediately after login (the server rejects/resets the first protected request). AES-128 tickets happen to work only because the key is already 16 bytes.

Affected code

impacket/smb3.py, SMB3.kerberosLogin() (line numbers as of master @ 8ea54feb; identical in the 0.13.1 release):

python
880:                 apCipher = _enctype_table[int(encAPRepPart['subkey']['keytype'])]()
881:                 apSessionKey = Key(apCipher.enctype, encAPRepPart['subkey']['keyvalue'].asOctets())
882:
883:                 sequenceNumber = int(encAPRepPart['seq-number'])
884:                 self._Session['SessionKey'] = apSessionKey.contents        # <-- full key (32 B for AES-256)
885:
886:             else:
887:                 self._Session['SessionKey']  = sessionKey.contents[:16]    # <-- correct: first 16 bytes

Note the inconsistency between line 884 (mutual-auth branch, full key) and line 887 (non-mutual branch, [:16]).

Steps to reproduce

Against a DC/server that issues AES-256 tickets and requires SMB signing or encryption:

python
from impacket.smbconnection import SMBConnection

c = SMBConnection(dc_host, dc_host)
c._SMBConnection.kerberosLogin(user, '', domain, kdcHost=kdc_ip,
                               useCache=True, mutualAuth=True)
c.connectTree('IPC$')   # first protected op -> server resets / rejects the session

With an AES-128 ticket the same flow works, which isolates the cause to the key length.

Expected behavior

Session.SessionKey is the first 16 bytes of the AP-REP sub-session key ([MS-SMB2] §3.2.5.3), so the derived signing/encryption keys match the server and the mutual-auth session works for all supported enctypes (including AES-256).

Actual behavior

The mutual-auth session negotiates successfully but the first signed/encrypted request fails; typical symptom is a connection reset ([Errno 104]) or an SMB error immediately after kerberosLogin, only when the ticket enctype is AES-256.

Suggested fix

Truncate to 16 bytes, matching the non-mutual branch and the spec:

diff
                 sequenceNumber = int(encAPRepPart['seq-number'])
-                self._Session['SessionKey'] = apSessionKey.contents
+                # [MS-SMB2] 3.2.5.3: Session.SessionKey is the first 16 bytes of the GSS key.
+                self._Session['SessionKey'] = apSessionKey.contents[:16]

Environment

  • Impacket: confirmed present in the latest release 0.13.1 (tag impacket_0_13_1, 2026-05-15) and on master (8ea54feb).
  • Python: 3.12
  • File: impacket/smb3.py
  • Reference: [MS-SMB2] §3.2.5.3 (Session.SessionKey = first 16 bytes of the GSS key).