Back to Home

Kerberos for developers: protocol and SSPI

The article breaks down the Kerberos protocol for AD: from impersonation and TGT to delegation and C++ code. SSPI, PKINIT, U2U examples for testing on one machine. Suitable for senior developers.

Kerberos: TGT, delegation and C++ code for SSPI
Advertisement 728x90

# Kerberos Protocol: Deep Dive for Developers

Kerberos solves the impersonation challenge: a service on machine A receives a request from a remote client and must perform operations on behalf of that client, including access to local resources. For this, a new access token is created based on the provided credentials. Without Kerberos, the service would use its own token, blocking access to files that require elevated privileges.

In a chained requests scenario, service A requests service B. Delegation lets you choose: impersonate from your own account or from the original client. Kerberos passes encrypted tickets containing the user's SID, groups, and PAC (Privilege Attribute Certificate).

Key Components:

Google AdInline article slot
  • Principal: an entity with a password (user, computer, service).
  • KDC (Key Distribution Center): stores passwords, issues TGT (Ticket Granting Ticket) and service tickets.
  • SPN (Service Principal Name): service identifier, often pointing to the account under which the service runs.

Kerberos distinguishes authentication from authorization: decrypting the ticket confirms identity, while the token determines privileges.

Message Structure and Transport

Kerberos messages use ASN.1 (PER/DER encoding per RFC 4120). They're transmitted over UDP/TCP on port 88. UDP works for short packets (TGT ~1-2 KB), TCP for larger ones (with PAC).

KDC in Active Directory combines AS (Authentication Service) and TGS (Ticket Granting Service). SRV records (_kerberos._tcp.<domain>) point to domain controllers.

Google AdInline article slot

AS-Exchange Process (Obtaining TGT):

  • Client → KDC: KRB_KDC_REQ (pre-auth with timestamp, encrypted with password or PKINIT).
  • KDC → Client: KRB_KDC_REP (TGT, encrypted with the client's long-term key; session key in pre-auth).
  • Client stores TGT in LSA (Local Security Authority).

TGS-Exchange (Service Ticket):

  • Client → KDC: KRB_TGS_REQ (TGT + authenticator + service name/SPN).
  • KDC → Client: KRB_TGS_REP (service ticket, service session key).

AP-REQ (with service ticket) is encapsulated in LDAP, HTTP Negotiate, SMB, RPC. Wireshark shows GSS-WRAP with NTLM/Kerberos token.

Google AdInline article slot

Encryption and Keys

The password is hashed into a long-term key (AES-256-CTs for Windows). Session keys are temporary, used to protect messages.

Example C++ code for Kerberos AES encryption using CNG (Cryptography API: Next Generation):

#include <windows.h>
#include <ncrypt.h>
#include <ntstatus.h>

NTSTATUS EncryptKerberosAES(
    PUCHAR key, ULONG keyLen,
    PUCHAR plaintext, ULONG ptLen,
    PUCHAR* ciphertext, ULONG* ctLen) {
    NCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;
    NTSTATUS status;

    status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, NULL, 0);
    if (!NT_SUCCESS(status)) return status;

    status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_CTS, sizeof(BCRYPT_CHAIN_MODE_CTS), 0);
    // Kerberos uses AES-CTS

    status = BCryptGenerateSymmetricKey(hAlg, &hKey, NULL, 0, key, keyLen);
    // ... encrypt logic with IV from Kerberos spec
    // Full code omitted for brevity

    BCryptCloseAlgorithmProvider(hAlg, 0);
    return status;
}

The code demonstrates setting up AES in CTS (Cipher Text Stealing) mode, specific to Kerberos.

Types of Delegation and Testing

Kerberos supports constrained and unconstrained delegation.

Delegation Options:

  • Simple: no delegation (service doesn't pass credentials further).
  • Unconstrained: full TGT forward (risky, deprecated).
  • Constrained: S4U2Proxy — service ticket only for specified SPN.
  • Resource-based constrained: on the service side (Windows Server 2012+).

Testing on a single machine: use klist, AcquireCredentialsHandle with SSPI. Example for U2U (User-to-User):

CredHandle cred;
TimeStamp expiry;
AcquireCredentialsHandle(NULL, L"Kerberos", SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, &expiry);
// U2U: impersonate without KDC, direct exchange

For PKINIT: pass X.509 cert to AcquireCredentialsHandle with SECPKG_CRED_CERTIFICATE. GSS-API is a wrapper for SSPI on Windows.

Cross-Domain Authentication and SPN

Trust accounts (name = domain) enable cross-domain authentication. A client from domain A requests a TGT for the trust principal in domain B.

SPN has no password — it identifies the host/user. Duplicate SPNs point to a single principal. The system determines the type by format: host/<fqdn>, HTTP/<fqdn>.

Managing Multiple Credentials:

  • ImpersonateHandleExplicit with logon.
  • LSA policy for multi-user SPN.
  • Custom GSS acceptor with checking multiple keys.

Key Takeaways

  • Kerberos is the GSS-API layer for single sign-on in AD; tickets contain PAC with SIDs/groups.
  • Delegation is critical for backend-to-backend; constrained minimizes risks.
  • Test SSPI: 3-5 lines for AcquireCredentialsHandle instead of boilerplate.
  • PKINIT and U2U extend passwordless scenarios.
  • ASN.1 + AES-CTs is the protocol core; monitor in Wireshark on port 88.

— Editorial Team

Advertisement 728x90

Read Next