Skip to content

smb: fix SMB 3.1.1 signing for Kerberos sessions - #43

Merged
psycep merged 1 commit into
mainfrom
fix-smb-kerberos-signing
Jul 19, 2026
Merged

smb: fix SMB 3.1.1 signing for Kerberos sessions#43
psycep merged 1 commit into
mainfrom
fix-smb-kerberos-signing

Conversation

@psycep

@psycep psycep commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

SMB2/3 signing was broken for Kerberos-authenticated sessions against a
signing-required SMB 3.1.1 server (e.g. a modern Windows DC). The session
established, but every signed operation failed: outbound requests were
rejected with STATUS_ACCESS_DENIED ("permission denied") and inbound
response signatures failed to verify. NTLM against the same host worked
fine. This is a pre-existing bug, unrelated to the recent transport work.

Root cause

For SMB 3.1.1 the signing/encryption keys are derived with the preauth
integrity hash as the KDF context, so that hash must cover exactly the
right SESSION_SETUP messages (MS-SMB2 3.2.5.3): every request, every
interim response, and not the final STATUS_SUCCESS response.

The code hashed leg 1's request and response unconditionally, then hashed
"the final request" again during key derivation. For NTLM's two-leg
exchange that happens to land on the correct set:

neg + req1 + resp1 + req2

But Kerberos completes in a single leg (immediate STATUS_SUCCESS), so the
same code produced:

neg + req1 + resp1 + req1

— wrongly including the final success response and double-hashing the
request. Wrong hash → wrong signing key → outbound rejected, inbound
mismatched.

The Kerberos session-key handling itself (truncating the AES256 key to 16
bytes) is correct per MS-SMB2 and matches Impacket, and is unchanged.

Fix

  • Fold each participating SESSION_SETUP message into
    PreauthIntegrityHashValue exactly once, at the point it is sent or
    received, excluding the final success response. Single-leg Kerberos now
    hashes neg + req1; two-leg NTLM is unchanged (neg + req1 + resp1 + req2).
  • Re-enable inbound signature verification in verify(). It had been
    stubbed to log a mismatch warning and return true unconditionally — a
    debug bypass that disabled inbound signature checking entirely. The MAC
    is now compared in constant time.

Testing

Verified end-to-end against a Windows Server 2019 DC (SMB 3.1.1,
signing required) with enforcement on:

  • Kerberos (AES256 / etype 18) and NTLM: session established,
    shares listed, C$ mounted, directory enumerated — no signature
    mismatch, no permission denied.
  • go build ./... and go test ./pkg/third_party/smb2/ pass.

The SMB 3.1.1 preauth integrity hash is the KDF context for the signing
and encryption keys. On the Kerberos single-leg SESSION_SETUP path
(immediate STATUS_SUCCESS), the hash was computed incorrectly: leg 1's
request and response were both folded in, then the request was hashed a
second time during key derivation, yielding

    neg + req1 + resp1 + req1

instead of the correct

    neg + req1

Per MS-SMB2 3.2.5.3 the final SESSION_SETUP response (STATUS_SUCCESS) is
excluded from the preauth hash. The wrong hash produced the wrong signing
key, so the DC rejected outbound requests (STATUS_ACCESS_DENIED) and
inbound response signatures failed to verify. NTLM was unaffected because
its two-leg exchange happens to hash exactly the right messages.

Fold each participating SESSION_SETUP message into the hash exactly once,
at the point it is sent or received, and exclude the final success
response. The two-leg NTLM path is unchanged (neg + req1 + resp1 + req2).

Also re-enable inbound signature verification in verify(), which had been
stubbed to print a mismatch warning and return true unconditionally -- a
debug bypass that disabled inbound signature checking entirely. Compare
the MAC in constant time.
@psycep
psycep merged commit 627c8b4 into main Jul 19, 2026
7 checks passed
@psycep
psycep deleted the fix-smb-kerberos-signing branch July 19, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant