Kerberos

I did not want to write this post. Not even a little bit. Of all the technology I take for granted, all the stuff that just sort of magically works in the background, Kerberos is the one I understood the least.

It also happens to be the de facto standard when it comes to Windows authentication in a domain environment, so it's kind of hard to avoid.

I've tried to capture all the important details, but be forewarned that the Kerberos rabbithole goes much deeper than this post ever will. If you want to go deeper, check the references toward the end of the post.

Let's dance.

Why Kerberos?

Kerberos operates with the assumption that the local network is insecure and all traffic may be tampered with or snooped. Good.

Since Kerberos doesn't implicitly trust the local network, it bakes in support for mutual authentication---not only does the client need to prove its identity to the server, the server must prove its identity to the client as well.

Contrast this with NTLMv2 which, although more thorough than its predecessor, the weak and frail NTLMv1, still offers robust support for Man-in-the-Middle (MitM) attacks unless SMB signing is enabled, which adds about 20% processing overhead to the transaction.

The Kerberos SSP

Let's start our hike through the fetid swamps of Kerberos at the beginning, where the magic starts.

As part of the Windows logon process, the Local Security Authority (LSA) will task the Security Support Provider Interface (SSPI) with finding it a suitable authentication provider. Since Windows 2000, Kerberos is the default choice for domain-joined computers.

Like NTLM, Kerberos has a Security Support Provider (SSP), provided by Kerberos.dll, that deals with the authentication wizardry.

Encryption

You couldn't have an authentication protocol operate with any legitimacy across an insecure network without making use of encryption. In almost all cases, Kerberos uses symmetric key encryption, with the lone exception being the use of smart cards which leverages asymmetric cryptography.

Kerberos implements these two types of encryption in three different ways:

The encryption algorithms supported by each version of Windows are as follows:

Operating System Algorithms Supported
Windows 2000 DES, RC4
Windows XP, Windows Server 2003 DES, RC4
Windows Vista, Windows Server 2008 DES, RC4, AES
Windows 7, Windows Server 2008 R2 DES, RC4, AES
Windows 8, Windows Server 2012 DES, RC4, AES
Windows 8.1, Windows Server 2012 R2 DES, RC4, AES
Windows 10, Windows Server 2016 DES, RC4, AES

Regardless of the symmetric algorithm used, the shared secret key will be the the recipient's NT hash.

Long-Term Symmetric Keys

Long-term symmetric keys are also referred to as master keys, and include:

Long-Term Asymmetric Keys

You'll only run into long-term asymmetric keys if you happen to be using smart cards containing public key certificates.

Short-Term Symmetric Keys

These are session keys, created for use with Ticket-Granting Tickets and Service Tickets.

Hold Up, What's a Kerberos?

So glad you finally asked! Kerberos, or Cerberus is a three-headed dog guarding the entrance to the underworld.

In the less exciting but still awesome Kerberos protocol, the three heads represent the Kerberos client, service, and Key Distribution Center (KDC). Users interface with Kerberos clients which request service from services running on servers and rely on the KDC for authentication and authorization.

I'm going to go over that again because getting the terminology straight is critical to understanding the next ~2700 words.

The KDC

The KDC is really what makes it feasible to have an authentication mechanism based on symmetric key cryptography. By having a trusted third party act as the authoritative repository for key material, the symmetric encryption keys never need to traverse the nasty filthy untrusted networkses unprotected.

In the world of Windows, specifically worlds full of domain-joined Windows machines, the KDC runs on each Domain Controller, which conveniently hosts a database of security principals1, better known as Active Directory.

In addition to storing all the fun stuff that Active Directory usually stores about a security principal (name, group membership, etc.), the KDC stores the long-term symmetric key, which it uses for encrypting messages destined for that principal.

The KDC also hosts the Ticket-Granting Server (TGS) which is responsible for issuing tickets. Tickets are how a user is granted access to a resource protected by Kerberos. No ticket, no ride. So how do we get a ticket?

Kerberos

I wrote this section three times before coming to conclusion that the simplest way to talk about Kerberos is by talking about the messages it uses to accomplish the task.

NTLM Challenge/Response

KRB_AS_REQ - Kerberos Authentication Service Request

This message is sent by the client during logon and contains the user principal name (UPN), the domain name associated with the account, and the timestamp of the client, encrypted with the MD4 hash of the user's password. The encrypted timestamp is known as the Pre-Authentication Data. Finally, the whole shebang is sent.

1
KRB_AS_REQ = UPN + DomainName + encrypt(userLTK, timestamp)

Once the KDC receives the KRB_AS_REQ message it retrieves its copy of the client's long-term key from the client's Active Directory object and uses it to decrypt the Pre-Authentication Data containing the timestamp.

The KDC checks the decrypted timestamp and if everything looks good, the client is verified. If this seems like a pretty weak means of authentication, just remember that decrypting a timestamp with the incorrect key will result in garbage that looks nothing like a timestamp.

KRB_AS_REP - Kerberos Authentication Service Response

The KDC responds by creating a logon session key for subsequent communication between the user and the Ticket-Granting Server (TGS). It will also create a TGT2 which is just a Service Ticket for the TGS running on the KDC. XYZ, LMNOP.

The user's logon session key is encrypted using the user's long-term key. The TGT is also encrypted, but the krbtgt account's long-term key. Both of these keys are the respective account's NT hash, which is just the password passed through the MD4 hash function.

The two encrypted messages are then sent back to the client.

1
2
KRB_AS_REP = encrypt(userLTK, user's logon session key) +
             encrypt(KDCLTK, user's logon session key + Authorization Data)

When the client receives the KRB_AS_REP message, it decrypts the user's logon session key with its local copy of the user's long-term key provided during logon and then discards the long-term key. All future communication with the KDC will use the user's logon session key.

The whole point of the KRB_AS_REQ and KRB_AS_REP message pair is to authenticate the user, then provide the client with a means of requesting services from other domain resources without continually having to enter its credentials again.

You can just think of the TGT as a domain-wide session cookie, allowing the user to log on to additional servers without having to continually re-enter credentials. When the user wants to access a new server, the client will just present the TGT to the KDC and obtain a Service Ticket. Since the TGT is protected by the krbtgt account's NT hash, the user can't modify this to grant themselves extra privileges.

When the NT hash for krbtgt is stolen, it can be used to issue arbitrary TGTs. This is known as a Golden Ticket attack.

KRB_TGS_REQ - Kerberos Ticket-Granting Service Request

Before the user can access either local or network resources. It must obtain a Service Ticket for the target service from the TGS.

The KRB_TGS_REQ message contains:

The Authenticator is the timestamp of the client, encrypted with the user's logon session key. Thinking back to the KRB_AS_REQ Pre-Authentication data, the Authenticator serves the same function here. It proves that the user is who they claim to be, since only the user would have access to the user's logon session key.

The whole package is then encrypted and sent.

1
2
3
KRB_TGS_REQ = name of target computer + name of target computer's domain +
              encrypt(user's logon session key, Authenticator) +
              TGT

This tells the KDC which server the user would like to access, authenticates the user using the user's logon session key, and provides the user's authorization data in the TGT.

KRB_TGS_REP - Kerberos Ticket-Granting Service Response

The TGS decrypts the TGT with its long-term key and then validates the Authenticator. If everything looks good, it creates a session key for the client to use when communicating with the target server and a Service Ticket for the target computer.

The KRB_TGS_REP message contains:

The KDC then encrypts the session key for the target server with the user's logon session key and then encrypts the Service Ticket with the server's long-term key. This again ensures that the user has access to the session key, but cannot modify their authorization data since it is protected by the server's long-term key.

1
2
KRB_TGS_REP = encrypt(userLTK, session key) +
              encrypt(serverLTK, Service Ticket)

When the request is for access to a workstation, the Service Ticket is encrypted with the workstation's long-term key. The LSA then builds an access token from the credentials contained within the Service Ticket and grants or denies access. We'll talk more about access tokens in later posts.

The Authorization Data contained in the Service Ticket contains all the group memberships for the security principal requesting access to a resource. It's how a service receiving the Service Ticket knows what the user is allowed to access.

The client has now used its TGT to request a Service Ticket for a specific resource. This Service Ticket not only contains the session key to be used for future client-server communications, but the user's Authorization Data---its group membership---that the server will use to grant access to resources.

The theft of these tickets is known as a Silver Ticket attack.

KRB_AP_REQ - Kerberos Application Server Request

When a user requests service from a server, it creates a KRB_AP_REQ message with the following information:

The server receives the message, decrypts the Service Ticket using its long-term key (NT hash), and decrypts the Authenticator contained within with the session key provided by the client.

Since the Service Ticket is encrypted with the server's long-term key and only the server and the KDC have access to that key, the server knows the session key is legitimate and that the Authorization Data came from the KDC.

KRB_AP_REP - Kerberos Application Server Response

If the mutual authentication flag has been set, the server will authenticate to the client as well. The server will use the session key to encrypt the time from the client's Authenticator and return it to the client.

Since the server received the Authenticator data in a Service Ticket protected by its own long-term key, returning just the Authenticator data proves it was able to access it.

The client then decrypts the Authenticator with the shared session key and verifies that it is accurate.

Authentication Process

Now that we've got the messages sorted out, let's walk through how this would actually look when a user needs to get something from a particular service.

  1. Check local cache for an existing Service Ticket for the target service. If found, it will just send a KRB_AP_REQ message to the service. Work complete.
  2. If an existing Service Ticket is not found, the client will check the local cache for a TGT. If a TGT is found, the user's logon session key is used to create an Authenticator, which is then sent along with the TGT to the KDC (KRB_TGS_REQ). The KDC validates the request and sends back a Service Ticket for the service. Proceed to step 1.
  3. If a TGT is not found, the client will request a TGT from the KDC (KRB_AS_REQ), then go to step 2.

The above process is used regardless of what the user is trying to access. No access is granted without a valid Service Ticket. This means that a user will have to receive a Service Ticket to access the workstation they're logging on to.

Access Tokens

We're going to get a little more into access tokens in future posts, but I do want to talk just a little bit about how Kerberos makes them while this is all fresh in your mind.

For now, just know that an access token is how processes can act on your behalf. It's like your stamp of approval on the work that it's doing. And Kerberos is the stamper.

So how do they get made?

Remember how the logon process returns a Service Ticket encrypted with the workstation's system key? Remember how that Service Ticket contains Authorization Data? That Authorization Data is used to create a Privileged Attribute Certificate (PAC), and in turn the access token.

Here's the workflow:

  1. The LSA decrypts the Service Ticket using its long-term key.
  2. The LSA then extracts the Authorization Data from the Service Ticket and creates the PAC.
  3. The LSA queries the local SAM database to find out whether the user is in any local security groups. If they are, those SIDs get added to the PAC.
  4. The PAC, now containing all domain and local group memberships, is now used to build the access token.
  5. A handle to the access token is passed to Winlogon, which starts the shell (explorer.exe).
  6. Any further processes created by the user inherit that access token, leaving a delightful opportunity for token theft---more on this later.

ELI5

When a user wants to access any service (including the local workstation it first logs on to) in a Windows domain that uses Kerberos, it needs a Service Ticket. It needs a Service Ticket for every service it wants to connect.

To get a Service Ticket, the client needs to talk to the Ticket-Granting Server (TGS), and to talk to the TGS, it needs a special Service Ticket. The Service Ticket for the TGS is known as the Ticket-Granting Ticket (TGT), which is issued by the KDC.

Now let's go the other way.

When a client first communicates with the KDC, it encrypts its local timestamp with the NT hash of the user. The KDC verifies the client by decrypting that timestamp. Since the timestamp will be horribly garbled unless it is decrypted with the correct key, if the timestamp is valid, the client is verified.

The KDC then sends the TGT to the client, who uses it to request Service Tickets from the TGS (also hosted on the KDC) as it requires them. The Service Tickets contain both a session key and the user's group memberships, and are encrypted with the target server's long-term key.

When the server receives the Service Ticket, it decrypts it with its own NT hash, then uses the session key to decrypt the Authorization Data, which it uses to determine whether the user should or should not be allowed access. The session key is then used to encrypt all future communication with the client.

References


  1. A security principal is just a fancy way to say "an entity recognized by a security system", such as a user. ↩︎

  2. The TGT has a lifetime of 10 hours by default. ↩︎

<<
>>