moex0
moex0
  • whoami
    • /root/usr/moex0
  • Articles
    • Demystifying Kerberos
    • Investigating APT29 Exploiting TeamCity CVE-2024-27198
Powered by GitBook
On this page
  • 1. Why Kerberos?
  • 2. What is Kerberos?
  • 3. Main Aims of Kerberos
  • 4. Kerberos Components & Terms
  • 4.1 Key Distribution Center (KDC)
  • 4.2 Tickets
  • 4.3 KRBTGT Service Account
  • 4.4 Keys
  • 4.5 Encryption Key
  • 4.6 Authenticator
  • 4.7 Replay Cache
  • 4.8 Credential Cache
  • 5. How Kerberos Works
  • 5.1 AS_REQ
  • 5.2 KRB_AS_REP
  • 5.3 TGS_REQ
  • 5.4 TGS_REP
  • 5.5 AP_REQ
  • 6. Pre-Authentication
  • 6.1 Pre-authentication Disabled
  • 6.2 Pre-authentication Enabled
  • References
  1. Articles

Demystifying Kerberos

Previous/root/usr/moex0NextInvestigating APT29 Exploiting TeamCity CVE-2024-27198

Last updated 4 months ago

In this article, I'll discuss the Windows Kerberos authentication process in a detailed manner. I often found some concepts not accurately documented while reviewing this topic, so I decided to write this article demystifying Kerberos authentication in a clear and precise way.

1. Why Kerberos?

In a Windows Active Directory environment, when a client wants to access a specific application (or service) over the network, the client authenticates with the domain controller, which acts as the centralized authentication management server.

Before Kerberos, when authenticating over an untrusted network, sending passwords in plaintext or transmitting password hashes (like LM/NTLM) is insecure, as they can be intercepted (either stealing the plaintext password, or the LM/NTLM hash) and used for unauthorized access.

And if sending the hash over the network logs you in, it means that anyone who has the hash can log in the same as you, this is called hash spoofing or Pass-the-Hash (PtH).

2. What is Kerberos?

Kerberos is considered to be the most secure form of authentication exchange in the Windows environment, but the way it’s facilitated with the use of tickets is its own idea of authentication.

It’s designed to provide reliable authentication over open and insecure networks, where communications may be intercepted. This can help protect your authentication process in transit, even if sniffed and observed off the network.

Kerberos addresses the weaknesses of other authentication methods by providing end-to-end protection using ticket-based authentication, mutual authentication between the client and server, and strong cryptography.

3. Main Aims of Kerberos

We need to understand some of the aims that the protocol wishes to achieve before getting into details about the Kerberos authentication system. Some of the aims are:

  • The user's password must never travel over the network.

  • The user's password must never be stored in any form on the client machine, and it must be immediately discarded after being used.

  • Achieving Single Sign-On (SSO), where the user is prompted to enter a password only once per work session, allowing the user to access all the services he/she is allowed to access, without having to re-enter the password during this session.

4. Kerberos Components & Terms

Before getting into the details of the Kerberos authentication process, we need to understand core components and terms, which will be used later when discussing more details about it.

4.1 Key Distribution Center (KDC)

The authentication server in a Kerberos environment is called KDC. Since it resides entirely on a single physical server, it can be logically considered divided into three parts:

  • Database

  • Authentication Server (AS)

  • Ticket Granting Server (TGS)

4.1.1 Database

The Authentication Server (AS) and Ticket Granting Server (TGS) verify the principals (entries) and the secret keys by checking them in the KDC database during the authentication process.

The AS and TGS do not actually contain this information included in Figure 3. This information is included in the KDC database, and the AS and TGS only check it by accessing the KDC database and checking the information needed to be verified. It's just visualized like that for simplicity and clearer understanding.

4.1.2 Authentication Server (AS)

The Authentication Server (AS) is the part of KDC that replies to the initial authentication request from the client. In response to the initial authentication request, the AS issues a special known ticket which is known as Ticket Granting Ticket (TGT).

If users are actually who they say they are, they can use the TGT to request other service tickets (which the user wants to access) from TGS, without having to re-enter passwords. This achieves the concept of Single Sign-On (SSO).

4.1.3 Ticket Granting Server (TGS)

The Ticket Granting Server (TGS) is the KDC component that distributes the service tickets to clients with valid TGT, guaranteeing the authenticity of the identity that requests access to resources on the application servers.

It can be considered as an application server that provides the issuing of service tickets as a service (TaaS).

4.2 Tickets

A ticket is something a client presents to an application server (either the KDC or a service) to demonstrate the authenticity of its identity. Tickets are issued by the KDC (AS and TGS), and are encrypted using a secret key of the service they’re intended for.

Since the shared secret is only shared between the KDC and the server providing the service, not even the client can know or change the contents of the ticket.

Keep in mind, a principal usually refers to the username of that specific client or service. For example:

Client

  • Default Format — Name[/Instance]@REALM

    • User — moex0@EXAMPLE.COM

    • Admin — moex0/admin@EXAMPLE.COM

      • Where moex0 is the username, and admin is the instance to differentiate between a normal user and an admin.

Service

  • Default Format — Service/Hostname@REALM

    • FTP Service — ftp/server.example.com@EXAMPLE.COM

      • Where ftp is the service name, and server.example.com is the FQDN (Fully Qualified Domain Name) of the machine providing the requested service.

The main information contained in a ticket includes:

  • PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​: The requesting user's principal

  • PrincipalService\mathtt{Principal_{Service}}PrincipalService​: The principal of the service the request it is intended for

  • The IP address of the client machine from which the ticket can be used, included in the IP_list\mathtt{IP\_list}IP_list.

  • Timestamp\mathtt{Timestamp}Timestamp: The date and time (in timestamp format).

  • Lifetime\mathtt{Lifetime}Lifetime: The ticket's maximum lifetime.

The Why of Tickets' Lifetime

Each ticket has a lifetime, which is by default 10 hours (600 minutes). This is essential since the authentication server no longer has control over any issued ticket. Even though the realm admin can prevent the issuing of new tickets for a certain user at any time, it cannot prevent users from using the tickets they already posses. This is the reason for limiting the lifetime of the tickets in order to limit any abuse over time.

4.3 KRBTGT Service Account

KRBTGT is a default account that exists in all domains of an Active Directory. Its purpose is to act as a KDC service account (acting as the authentication service for a given domain) for domain controllers.

The password of the KRBTGT account should be strong and highly protected because if compromised by an adversary, they would be able to forge arbitrary TGTs, known as Golden Tickets.

The KRBTGT account is disabled by default, as only its password is used to derive the encryption key, that will be used to encrypt the TGT. This adds a layer of protection to the account.

The KRBTGT service has a unique principal, which differs from the users and services principals mentioned above.

KRBTGT — krbtgt/REALM@REALM

Why is the hostname and realm for the KRBTGT service REALM@REALM?

4.4 Keys

4.4.1 Long-term Keys

Users and services share a secret with the KDC, which is stored in the KDC database.

  • For services, it’s their secret key (set by the administrator).

These keys are called long-term keys (we'll call them secret keys), since they do not change when the work session changes.

Maybe you're asking, why isn't the user's secret key stored on the client and only stored in the KDC database, unlike the service which has its secret key stored on its server and the KDC database?

The user's secret key is not stored on the client in Kerberos because it is stored securely on the KDC. The KDC is responsible for managing and distributing the keys used for authentication and encryption in Kerberos. This ensures that the keys are not compromised if the client is compromised or if the client's storage is accessed by an unauthorized party.

Meanwhile, for services, they do not need to type in a password because the secret key is already set by the administrator and shared between the KDC and the service pre-authentication (Pre-shared Key).

4.4.2 Session Keys

It's also necessary that a user shares a secret with the service (KRBTGT and application servers), at least for the time in which the client has a work session open on a server. This key is generated by the KDC when a ticket is issued, and it’s called a Session Key.

Session keys are generated for:

  • Securing Communications: The session key is used to encrypt communications between the client and the server, ensuring that the data exchanged during the session is protected from eavesdropping and tampering by unauthorized parties.

Session keys play a fundamental role in proving the authenticity of the user.

4.5 Encryption Key

string2key is a one-way hash function, which means that it's irreversible. It transforms the unencrypted user's password into an encryption key, which will further be used for encrypting data. The encryption key cannot determine the password (unless by brute force), which adds a layer of security in case the encryption key gets compromised.

The string2key function is called every time the user changes the password or enters it for authentication.

4.5.1 Salt

In Kerberos 5, the concept of password salt has been introduced. A string (salt) is to be concatenated to the unencrypted password before applying the string2key function to obtain the encryption key. Kerberos 5 uses the same principal of the user principal as salt:

Where, Kuser\mathtt{K_{user}}Kuser​ is the encryption key of the user, and Puser\mathtt{P_{user}}Puser​ is the unencrypted password of the user.

Adding salt also ensures that even if two different principals have the same unencrypted password, will still have different encryption keys.

The KRBTGT service account secret key KTGS\mathtt{K_{TGS}}KTGS​ undergoes the same process as the generation of the user's secret key, which will only be used to encrypt/decrypt the Ticket Granting Ticket (TGT).

4.6 Authenticator

An attacker could capture the ticket when it’s sent by a legitimate client, and send it illegitimately to obtain unauthorized access to the service. Even if we include the IP addresses of the machine in the ticket, it is known that in an open and insecure network, addresses can be easily spoofed.

To solve this problem, we can take advantage of the fact that the client and the server have a session key ( SKTGS\mathtt{SK_{TGS}}SKTGS​ or SKService\mathtt{SK_{Service}}SKService​ ) in common that only they know (and also the KDC since it generated it, but it's trusted by default). Therefore, along with the request containing the ticket, the client adds another packet, called the authenticator.

Authenticator={ PrincipalClient , Timestamp } SKTGS\mathtt{Authenticator = \{\:Principal_{Client}\:,\:Timestamp\:\}\:SK_{TGS}}Authenticator={PrincipalClient​,Timestamp}SKTGS​

What if there’s a possibility that the attacker can steal both the ticket and the authenticator and use them during the 2 minutes of validity? Here comes the concept of Replay Cache.

4.7 Replay Cache

Although this is very difficult to happen that the attacker steal both, the ticket and the authenticator, it’s not impossible. To solve this problem, Replay cache has been introduced in Kerberos 5.

In application servers and also in TGS, there exists a capacity to remember the authenticators that have arrived within the last 2 minutes and reject them if they’re replicas. Accordingly, the attacker wouldn’t be able to replay the request. Even if the attacker reached the server before the original user, the user access to the server would be denied, and this would indicate a breach.

4.8 Credential Cache

The client never keeps the user's password PUser\mathtt{P_{User}}PUser​, nor does it memorize the secret key KUser\mathtt{K_{User}}KUser​ obtained by applying string2key. They are used to decrypt the replies from KDC and are immediately discarded.

However, to implement the Single Sign-On (SSO) characteristic, where the user is asked to enter the password just once per work session, it is necessary to memorize the ticket ( TGT\mathtt{TGT}TGT ) and the related session ( SKTGS\mathtt{SK_{TGS}}SKTGS​ ) key. The place where this data is stored is called the Credential Cache.

5. How Kerberos Works

To streamline the explanation of the authentication process, we'll give a simple abstract example of how Kerberos works, then we'll get into more details later on.

Let's assume Bob decided to visit an amusement park. He went to the ticket booth (TGS\mathtt{TGS}TGS) at the front door (KDC\mathtt{KDC}KDC), and bought an admission ticket (TGT\mathtt{TGT}TGT), which will give him access to the front door (KDC\mathtt{KDC}KDC) only for that day (or a limited timestamp). Bob went past the front door into the park and found an amazing ride called the "file server ride" (the service).

Bob reached out to the person at the ride's gate (the service) and asked him if he could try the file server ride and showed him the admission ticket (TGT\mathtt{TGT}TGT), the person told him that he needed another ticket (TService\mathtt{T_{Service}}TService​) specifically for the file server ride in order to have to access it.

Bob went back to the ticket booth (TGS\mathtt{TGS}TGS) and asked the person at the ticket booth to give him a file server ride ticket ( TService\mathtt{T_{Service}}TService​ ). The person asked to show him the ticket from the front gate (the admission ticket TGT\mathtt{TGT}TGT) before he could give him the file server ride ticket (TService\mathtt{T_{Service}}TService​). Bob shows him the admission ticket (TGT\mathtt{TGT}TGT) and puts it back into his pocket. The person at the ticket booth asked him some other questions to verify that the admission ticket belonged to him and that he didn't steal it ( Authenticator\mathtt{Authenticator}Authenticator ). After verification, the person at the ticket booth (TGS\mathtt{TGS}TGS) then gives Bob the file server ride ticket (TService\mathtt{T_{Service}}TService​). This means that Bob can request any ride he wants to access using this admission ticket (TGT\mathtt{TGT}TGT), as long as it's valid and didn't expire (TGT\mathtt{TGT}TGT lifetime).

Bob goes to the file server ride gate and shows the person the file server ride ticket (TService\mathtt{T_{Service}}TService​), granted access to the ride. Bob can access the file server ride as long as the ticket is valid and didn't expire (TService\mathtt{T_{Service}}TService​ lifetime).

To demonstrate the Kerberos authentication process, we'll assume that a specific user wants to access resources on a specific application server, let's say an FTP server, from a specific client.

5.1 AS_REQ

AS_REQ=( PrincipalClient , PrincipalService , IP_list , Lifetime )\mathtt{AS\_REQ = (\:Principal_{Client}\:, \:Principal_{Service}\:, \:IP\_list\:, \:Lifetime\:)}AS_REQ=(PrincipalClient​,PrincipalService​,IP_list,Lifetime)

Where:

  • PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​: The principal of the user requesting authentication (e.g. moex0@EXAMPLE.COM).

  • PrincipalService\mathtt{Principal_{Service}}PrincipalService​: The principal of the service the ticket is being asked for, which would generally be krbtgt/REALM@REALM in the initial authentication.

  • IP_list\mathtt{IP\_list}IP_list: The list of IP addresses that are allowed to use the ticket.

  • Lifetime\mathtt{Lifetime}Lifetime: The maximum ticket validity time requested by the user.

There’s a special case where the PrincipalService\mathtt{Principal_{Service}}PrincipalService​ isn’t krbtgt/REALM@REALM. When the user wants to just use one service during a work session, they wouldn’t need Single Sign-On and may ask Authentication Server (AS) directly for the service ticket, skipping the request to the TGS TGS_REQ\mathtt{TGS\_{REQ}}TGS_REQ.

5.2 KRB_AS_REP

Upon receiving the previous request, the AS checks if the PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​ and PrincipalService\mathtt{Principal_{Service}}PrincipalService​ exist in the KDC database. If they exist, AS will start creating the reply AS_REP\mathtt{AS\_REP}AS_REP, which consists of two parts:

Session Key ( SKTGS\mathtt{SK_{TGS}}SKTGS​ )

The AS will randomly create a session key, let’s say SKTGS\mathtt{SK_{TGS}}SKTGS​, which will be used for protecting subsequent communications between the client and the TGS.

Ticket Granting Ticket ( TGT\mathtt{TGT}TGT )

The AS will issue a TGT which will include: PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​ and PrincipalService\mathtt{Principal_{Service}}PrincipalService​ (which's still krbtgt/REALM@REALM, as the user will subsequently communicate with TGS), IP list, data and time in timestamp format, ticket's lifetime, TGS session key SKTGS\mathtt{SK_{TGS}}SKTGS​.

TGT=( PrincipalClient , PrincipalService , IP_list , Timestamp , Lifetime ,SKTGS)\mathtt{TGT = (\:Principal_{Client}\:, \:\mathtt{Principal_{Service}}\:, \:IP\_list\:, \:Timestamp\:,\:Lifetime\:, SK_{TGS})}TGT=(PrincipalClient​,PrincipalService​,IP_list,Timestamp,Lifetime,SKTGS​)
AS_REP={ PrincipalService , Timestamp , Lifetime ,SKTGS }KUser { TGT }KTGS\mathtt{AS\_REP = \{\:{Principal_{Service}}\:,\:Timestamp\:,\:Lifetime\:, SK_{TGS}\:\}K_{User}\:{\{\:TGT\:\}K_{TGS}}} AS_REP={PrincipalService​,Timestamp,Lifetime,SKTGS​}KUser​{TGT}KTGS​

What happens when the client receives the AS_REP\mathtt{AS\_{REP}}AS_REP?

Why information already included in the TGT is sent again for the user in the session key part of the reply?

As we want to protect the information inside the TGT from tampering, the TGT is encrypted using the KRBTGT service account secret SKTGS\mathtt{SK_{TGS}}SKTGS​. If the TGT were to be encrypted using the user’s secret KUser\mathtt{K_{User}}KUser​, the user would be able to see what's inside the TGT and could tamper with the information included (such as setting the lifetime to 10 years). Similarly, if the client was compromised, the adversary would be able to tamper with the information inside the TGT and use it to gain unauthorized access. That’s why, another part of the reply (session key part) is encrypted and sent to the user to protect the TGT, as well as provide the user’s authenticity using the session key SKTGS\mathtt{SK_{TGS}}SKTGS​ and the Timestamp\mathtt{Timestamp}Timestamp.

It’s important to note that the application server never communicates directly with the KDC. It only receives the Service Ticket TService\mathtt{T_{Service}}TService​ through the client wishing to access it.

5.3 TGS_REQ

At this point, the user authenticated with the AS, but still doesn’t have the ticket to access the requested service. The user sends a request TGS_REQ\mathtt{TGS\_REQ}TGS_REQ to the Ticket Granting Server (TGS) by:

Authenticator={ PrincipalClient , Timestamp } SKTGS\mathtt{Authenticator = \{\:{Principal_{Client}}\:,\:Timestamp\:\}\:SK_{TGS}}Authenticator={PrincipalClient​,Timestamp}SKTGS​
  • Creating a request packet TGS_REQ\mathtt{TGS\_{REQ}}TGS_REQ containing the PrincipalService\mathtt{Principal_{Service}}PrincipalService​ of the service the ticket is needed for, Lifetime\mathtt{Lifetime}Lifetime, the Authenticator\mathtt{Authenticator}Authenticator just created, and the TGT\mathtt{TGT}TGT (which's already encrypted using KTGS\mathtt{K_{TGS}}KTGS​):

TGS_REQ=( PrincipalService , Lifetime , Authenticator ) { TGT }KTGS\mathtt{TGS\_{REQ} = (\:Principal_{Service}\:, \:Lifetime\:, \:Authenticator\:)\:{\{\:TGT\:\}K_{TGS}}}TGS_REQ=(PrincipalService​,Lifetime,Authenticator){TGT}KTGS​

5.4 TGS_REP

When the TGS receives the request TGSREQ\mathtt{TGS_{REQ}}TGSREQ​, it first verifies that PrincipalService\mathtt{Principal_{Service}}PrincipalService​ exists in the KDC database. If it exists, it decrypts the TGT using the KRBTGT secret key KTGS\mathtt{K_{TGS}}KTGS​, and extracts the session key SKTGS\mathtt{SK_{TGS}}SKTGS​, which is subsequently used to decrypt the authenticator in order to verify the user. Before issuing the requested service ticket TService\mathtt{T_{Service}}TService​, the following conditions have to be checked and verified:

  • The TGT has not expired.

  • The PrincipalClient \mathtt{Principal_{Client}}PrincipalClient​ which exists in the authenticator matches the one present in the TGT.

  • The Authenticator\mathtt{Authenticator}Authenticator is not already present in the replay cache and has not expired.

  • If the IP_list\mathtt{IP\_{list}}IP_list is not null, it checks that the source IP of the request packet is one of those contained in the list.

These conditions are being checked to prove that the TGT really belongs to the user who made the request. If verified, the TGS will start forging the reply:

Session Key ( SKService\mathtt{SK_{Service}}SKService​ )

Randomly creates a session key SKService\mathtt{SK_{Service}}SKService​, which will be used for encrypting subsequent communications between client and service.

Service Ticket ( TService\mathtt{T_{Service}}TService​ )

Creates a service ticket TService\mathtt{T_{Service}}TService​, with mostly similar information to that included in the TGT. What's different is the service principal PrincipalService\mathtt{Principal_{Service}}PrincipalService​, which will be the requested service principal, and the session key included SKService\mathtt{SK_{Service}}SKService​, which will be the service session key.

It then sends the reply message TGS_REP\mathtt{TGS\_{REP}}TGS_REP containing the requested service ticket TService\mathtt{T_{Service}}TService​ encrypted with the service secret key KService\mathtt{K_{Service}}KService​, along with the other part of the reply message which includes the session key SKService\mathtt{SK_{Service}}SKService​ and other information all encrypted with the TGS session key SKTGS\mathtt{SK_{TGS}}SKTGS​:

TService=( PrincipalClient , PrincipalService , IP_list , Timestamp , Lifetime ,SKService )\mathtt{T_{Service} = (\:Principal_{Client}\:, \:{Principal_{Service}}\:, \:IP\_list\:, \:Timestamp\:,\:Lifetime\:, SK_{Service}\:)}TService​=(PrincipalClient​,PrincipalService​,IP_list,Timestamp,Lifetime,SKService​)

It then sends the reply message TGSREP\mathtt{TGS_{REP}}TGSREP​ containing the requested service ticket TService\mathtt{T_{Service}}TService​ encrypted with the service secret key KService\mathtt{K_{Service}}KService​, along with the other part of the reply message which includes the session key SKService\mathtt{SK_{Service}}SKService​ and other information all encrypted with the TGS session key SKTGS\mathtt{SK_{TGS}}SKTGS​:

TGS_REP=( PrincipalService , Timestamp , Lifetime , SKService }SKTGS { TService }KService\mathtt{TGS\_{REP} = (\:Principal_{Service}\:, \:Timestamp\:,\:Lifetime\:, \:SK_{Service}\:\}SK_{TGS}\:{\{\:T_{Service}\:\}K_{Service}}}TGS_REP=(PrincipalService​,Timestamp,Lifetime,SKService​}SKTGS​{TService​}KService​

At this point, when the client receives the TGS_REP\mathtt{TGS\_{REP}}TGS_REP, it'll decrypt the session key part using SKTGS\mathtt{SK_{TGS}}SKTGS​, and extract the new service session key SKService\mathtt{SK_{Service}}SKService​. It'll then cache both the service ticket TService\mathtt{T_{Service}}TService​ and the service session key SKService\mathtt{SK_{Service}}SKService​ in the credential cache. This will achieve SSO with the requested service, as long as the ticket didn't expire.

5.5 AP_REQ

Authenticator={ PrincipalClient , Timestamp } SKService\mathtt{Authenticator = \{\:Principal_{Client}\:,\:Timestamp\:\}\:SK_{Service}}Authenticator={PrincipalClient​,Timestamp}SKService​
  • Creates a request packet AP_REQ\mathtt{AP\_{REQ}}AP_REQ containing the Authenticator\mathtt{Authenticator}Authenticator just created, and the service ticket TService\mathtt{T{Service}}TService (which's already encrypted using KService\mathtt{K_{Service}}KService​):

AP_REQ=Authenticator { TService }KService\mathtt{AP\_REQ = Authenticator\:{\{\:T_{Service}\:\}K_{Service}}} AP_REQ=Authenticator{TService​}KService​

When the application server receives the request AP_REQ\mathtt{AP\_{REQ}}AP_REQ, it decrypts the ticket TService\mathtt{T_{Service}}TService​ using the requested service secret key KService\mathtt{K_{Service}}KService​, and extracts the service session key SKService\mathtt{SK_{Service}}SKService​, which is subsequently used to decrypt the Authenticator\mathtt{Authenticator}Authenticator to prove the user's authenticity.

  • The service ticket TService\mathtt{T_{Service}}TService​ has not expired.

  • The PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​ which exists in the authenticator matches the one present in the ticket.

  • The Authenticator\mathtt{Authenticator}Authenticator is not already present in the replay cache and has not expired.

  • If the IP_list\mathtt{IP\_list}IP_list is not null, it checks that the source IP of the request packet AP_REQ\mathtt{AP\_REQ}AP_REQ is one of those contained in the list.

6. Pre-Authentication

Since Kerberos doesn’t require the AS to authenticate the user before sending the TGT (only checks if the client and server principals exist in the KDC database), a client doesn’t provide its password or any method to provide authenticity. Therefore, the AS cannot validate the client’s identity and doesn’t provide any assurance of the identity. Accordingly, an attacker can send legitimate client/server principals (impersonate a user), requesting a TGT.

6.1 Pre-authentication Disabled

The attacker then would simply request another TGT, to have a valid timestamp and lifetime, and decrypt it with the secret key he obtained. This would give him the ability to tamper with the information included in the TGT and gain unauthorized access.

6.2 Pre-authentication Enabled

With pre-authentication enabled, the AS will request the user to send a Timestamp\mathtt{Timestamp}Timestamp, encrypted with the user’s secret KUser\mathtt{K_{User}}KUser​ as the encryption key. If the AS reads a valid timestamp by decrypting it with the user's secret key (which’s available in the KDC database), the AS knows that this request isn’t a replay of a previous request and that it’s included within the timestamp tolerance period. This ensures that the attacker cannot directly ask the KDCs for the encrypted tickets to brute force offline.

In order for the attacker to have a TGT, the attacker has to encrypt a timestamp with a password and offer it to the KDC to request the TGT. This process would be repeated over and over while trying to brute-force the pre-authentication packet. However, the KDC log will record the entry every time the pre-authentication fails.

Keep in mind that pre-authentication doesn’t prevent the attacker from sniffing the client’s encrypted timestamp message to the KDC, which if sniffed, the attacker can brute force it offline. Pre-authentication just adds an extra layer of security, where the attacker cannot request a ticket without authentication, which makes the attacker's attempts more visible and easier to detect.

To add one more layer of security, it’s recommended to use lengthy passwords and have a good password rotation policy in the domain in order to make offline brute-forcing ineffective.

References

The user's password should never be stored in an unencrypted form, even in the authentication server (or KDC) database (refer to ).

It’s a container for entries associated with users and services. As an abstract, each entry contains a principal (which can be either a client or a service) and the corresponding long-term secret key (described in ).

SKService\mathtt{SK_{Service}}SKService​: The session key (this has a fundamental role in authentication, described in ).

A key derived from the KRBTGT account’s password KTGS\mathtt{K_{TGS}}KTGS​ (refer to for KRBTGT service account secret key generation) is used to encrypt the Ticket Granting Ticket (TGS) before being sent to the client, in order to protect it from tampering.

Because the KRBTGT exists in the KDC, and as the TGT is issued from the AS and handed by the client to the TGS, this means that it goes from the KDC to the KDC (refer to ).

For users, the secret is the key derived from their password (refer to ).

KRBTGT service account secret key (refer to ).

Authentication: The session key is generated, encrypted with the client's secret key (long-term key), and sent back to the client, ensuring that only the legitimate user can decrypt and access the session key. This process helps authenticate the client to the server (discussed more in-depth in ).

As we mentioned in , one of the aims of Kerberos protocol is to prevent the user's password from being stored in an unencrypted form, not even in the KDC database. Therefore, string2key function has been introduced.

Even if the user principal PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​ is present in the ticket, it’s not enough to guarantee the authenticity of the client (refer to the authentication process in ). Why?

The authenticator includes the PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​ and Timestamp\mathtt{Timestamp}Timestamp, and encrypts them with the session key. An example of the authenticator in case of client requests a service ticket from the TGS is shown below (refer to ):

The server which offers the service will decrypt the ticket upon receiving the request, and extract the session key. If the server is actually who he/she says, the server will be able to decrypt the authenticator, using the extracted session key, and extracting the timestamp. If the timestamp differs from the server time by less than 2 minutes (tolerance can be configured), then the authentication is successful (refer to ). This shows the criticality of synchronization between machines belonging to the same realm.

This abstraction was an inspiration from .

The user sends an initial authentication request to the Authentication Server (AS), requesting a Ticket Granting Ticket ( TGT\mathtt{TGT}TGT ). This request is not necessarily encrypted (discussed later in ).

The AS_REP\mathtt{AS\_{REP}}AS_REP is then generated containing the TGT, encrypted using the KRBTGT service account secret KTGS\mathtt{K_{TGS}}KTGS​ (discussed in ), sent with the session key and some other information, encrypted with the user’s secret KUser\mathtt{K_{User}}KUser​, as described in the equation below:

At this point, when the client receives AS_REP\mathtt{AS\_REP}AS_REP, it’ll ask the user to enter the password. As described in , the salt is concatenated with the password and passed to string2key function, resulting in KUser\mathtt{K_{User}}KUser​, which will be used to decrypt the part of the message that was encrypted by the KDC using the KUser\mathtt{K_{User}}KUser​ stored in the KDC database. If it’s decrypted successfully, this indicates that the user is really who he/she says.

In order to achieve Single Sign-On, the client will then extract the session key SKTGS\mathtt{SK_{TGS}}SKTGS​ from the decrypted part of the reply, and store it and the TGT in the user’s credential cache (refer to ).

Creating an authenticator (refer to ) with the PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​, Timestamp\mathtt{Timestamp}Timestamp, and encrypt them both using SKTGS\mathtt{SK_{TGS}}SKTGS​:

As the client now has the service ticket TService\mathtt{T_{Service}}TService​ and the service session key SKService\mathtt{SK_{Service}}SKService​, it can now ask the service for access to whatever resources it needs via a AP_REQ\mathtt{AP\_{REQ}}AP_REQ message. AP_REQ\mathtt{AP\_{REQ}}AP_REQ uses a similar strategy to the one used in the TGS_REQ\mathtt{TGS\_{REQ}}TGS_REQ (refer to ):

Creates an authenticator (refer to ) with the PrincipalClient\mathtt{Principal_{Client}}PrincipalClient​, Timestamp\mathtt{Timestamp}Timestamp, both encrypted using service session key SKService\mathtt{SK_{Service}}SKService​:

Before granting access to the user, the conditions (similarly mentioned in ) should be positive to verify the user's authenticity:

It's not surprising that the previous strategy is very similar to the one used in the TGS to check the authenticity of the user, as the TGS can be considered as an application server whose service is to provide tickets to users (as mentioned in ).

The attacker would request a TGT, and the TGT will be issued (after verifying the client and service principals), encrypted with the KRBTGT secret key KTGS\mathtt{K_{TGS}}KTGS​, and sent as a reply (refer to ) to the attacker requesting it. The attacker would then perform an offline brute-force or dictionary attack on the TGT. This process wouldn’t appear in the KDC logs except only as a single request for TGT. After successfully decrypting the TGT, the attacker now has the KTGS\mathtt{K_{TGS}}KTGS​, which he can use to decrypt any TGT.

section 4.1
section 4.4
section 4.4
section 4.5
section 5
section 4.5
section 4.3
section 5
section 3
section 5
section 5.3
section 5.4
@BryanOnSecurity
section 6
section 4.5
section 4.5
section 4.8
section 4.6
section 5.3
section 4.6
section 5.3
section 4.1.3
section 5.2
https://datatracker.ietf.org/doc/html/rfc4120#page-29
https://kerberos.org/software/tutorial.html
https://learn.microsoft.com/en-us/windows-server/security/kerberos/kerberos-authentication-overview
https://www.acsac.org/2007/papers/30.pdf
https://learn.microsoft.com/en-us/archive/technet-wiki/23559.kerberos-pre-authentication-why-it-should-not-be-disabled
Figure 1: Pass-the-Hash (PtH)
Figure 2: Key Distribution Center (KDC)
Figure 3: Example on a KDC Database
Figure 4: Authentication Server (AS)
Figure 5: Ticket Granting Server (TGS)
Figure 6: Ticket
Figure 7: Example on information included in the ticket
Figure 8: KRBTGT Service Account Disabled By Default
Figure 9: Long-term Keys
Figure 10: User's Secret Key Generation
Figure 11: KRBTGT Service Account Key Generation
Figure 12: Authenticator encrypted with the TGS session key
Figure 13: TGS Replay Cache
Figure 14: User Credential Cache For Achieving SSO With KDC
Figure 15: Overview on Kerberos Authentication Process
Figure 16: Client Requesting Initial Authentication From the Authentication Server (AS_REQ)
Figure 17: AS checking if the client and service principals exist in the KDC database
Figure 18: Ticket Granting Server (TGS) session key
Figure 19: Ticket Granting Ticket (TGT)
Figure 20: Authentication Server Reply (AS_REP)
Figure 21: Client Receiving The AS_REP
Figure 22: Authenticator encrypted with TGS session key
Figure 23: Client sending a request to TGS to obtain a service ticket (TGS_REQ)
Figure 24: TGS checking if the service principal exists in the database
Figure 25: TGS receives the client request for the service ticket
Figure 26: Service Session Key
Figure 27: Service Ticket
Figure 28: Client receiving the TGS reply (TGS_REP) which includes the service ticket and session key
Figure 29: Client extracting session key and saving it and the service ticket in credential cache
Figure 30: User Authenticator
Figure 31: Client sending a request for the service to access resources (AP_REQ)
Figure 32: Application server receiving AP_REQ and verifying the request issuer
Figure 33: Attacker requesting a TGT from the Authentication Server (AS_REQ)
Figure 34: Client's pre-authentication data validated before issuing a TGT
Page cover image