Post

Kerberos Fundamentals

This post outlines the authentication flow of the Kerberos protocol and the exact data structures for each message during transfer.

Kerberos Fundamentals

I found most existing Kerberos protocol tutorials unsatisfactory — they’re either too noisy or lack sufficient detail. So I created this post with simplified, intuitive yet accurate diagrams. I also dive into the RFC to show the exact data structure for each message and where key information is stored during transfer.

Ticket Definition

A Ticket Granting Ticket (TGT) and a Ticket Granting Service (TGS) ticket share a similar structure, as defined in the RFC4120. Each consists of an unencrypted section that contains metadata, and an encrypted section that holds sensitive information such as credentials and session keys.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   Ticket          ::= [APPLICATION 1] SEQUENCE {

           tkt-vno         [0] INTEGER (5),  
           realm           [1] Realm,  
           sname           [2] PrincipalName,  
           enc-part        [3] EncryptedData -- EncTicketPart  
   } 
  
   -- Encrypted part of ticket  
   EncTicketPart   ::= [APPLICATION 3] SEQUENCE {  
           flags                   [0] TicketFlags,  
           key                     [1] EncryptionKey,  
           crealm                  [2] Realm,  
           cname                   [3] PrincipalName,  
           transited               [4] TransitedEncoding,  
           authtime                [5] KerberosTime,  
           starttime               [6] KerberosTime OPTIONAL,  
           endtime                 [7] KerberosTime,  
           renew-till              [8] KerberosTime OPTIONAL,  
           caddr                   [9] HostAddresses OPTIONAL,  
           authorization-data      [10] AuthorizationData OPTIONAL  
   }  
  
   -- encoded Transited field  
   TransitedEncoding       ::= SEQUENCE {  
           tr-type         [0] Int32 -- must be registered --,  
           contents        [1] OCTET STRING  
   }  
  
   TicketFlags     ::= KerberosFlags  
           -- reserved(0),  
           -- forwardable(1),  
           -- forwarded(2),  
           -- proxiable(3),  
           -- proxy(4),  
           -- may-postdate(5),  
           -- postdated(6),  
           -- invalid(7),  
           -- renewable(8),  
           -- initial(9),  
           -- pre-authent(10),  
           -- hw-authent(11),  
   -- the following are new since 1510  
           -- transited-policy-checked(12),  
           -- ok-as-delegate(13)

Workflow (High-level)


Note: The red key here is technically the long-term key of the Ticket Granting Service, which is a component of the KDC. For simplicity and readability, it is referred to here as the KDC long-term key.

Note: Technically, TGS stands for Ticket Granting Service, not a ticket. However, for simplicity and readability, I use TGS to refer to the Ticket Granting Service ticket, in contrast to the TGT.

AS-REQ

Authentication Service Request: Sent by the client to the KDC to request a TGT on behalf of the user.

An authenticator is encrypted with the user’s long-term key, which is also held by the KDC, to verify the user’s identity. Specifically, it sits in the padata field.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
AS-REQ          ::= [APPLICATION 10] KDC-REQ  
  
KDC-REQ         ::= SEQUENCE {  
        -- NOTE: first tag is [1], not [0]  
        pvno            [1] INTEGER (5) ,  
        msg-type        [2] INTEGER (10 -- AS -- | 12 -- TGS --),  
        padata          [3] SEQUENCE OF PA-DATA OPTIONAL  <========== Authenticator
                                    -- NOTE: not empty --,  
        req-body        [4] KDC-REQ-BODY  
}  
  
KDC-REQ-BODY    ::= SEQUENCE {  
        kdc-options             [0] KDCOptions,  
        cname                   [1] PrincipalName OPTIONAL  
                                    -- Used only in AS-REQ --, 
        realm                   [2] Realm  
                                    -- Server's realm  
                                    -- Also client's in AS-REQ --,  
        sname                   [3] PrincipalName OPTIONAL,  
        from                    [4] KerberosTime OPTIONAL,  
        till                    [5] KerberosTime,  
        rtime                   [6] KerberosTime OPTIONAL,  
        nonce                   [7] UInt32,  
        etype                   [8] SEQUENCE OF Int32 -- EncryptionType  
                                    -- in preference order --,  
        addresses               [9] HostAddresses OPTIONAL,  
        enc-authorization-data  [10] EncryptedData OPTIONAL  
                                    -- AuthorizationData --,  
        additional-tickets      [11] SEQUENCE OF Ticket OPTIONAL  
                                       -- NOTE: not empty  
}  

ASREQRoast Attack

When positioned as a man-in-the-middle (MitM), an attacker may capture AS-REQ pre-authentication messages that contain encrypted timestamps. The attacker can then crack those encrypted timestamps offline to recover the user’s password.

AS-REP

Authentication Server Response: Sent by the KDC to the client in response to an AS-REQ. It contains the TGT and a user-KDC session key. The TGT sits in the ticket field. The encrypted session key sits in the key field of the enc-part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
AS-REP          ::= [APPLICATION 11] KDC-REP  
  
TGS-REP         ::= [APPLICATION 13] KDC-REP  
  
  
KDC-REP         ::= SEQUENCE {  
        pvno            [0] INTEGER (5),  
        msg-type        [1] INTEGER (11 -- AS -- | 13 -- TGS --),  
        padata          [2] SEQUENCE OF PA-DATA OPTIONAL  
                                -- NOTE: not empty --,  
        crealm          [3] Realm,  
        cname           [4] PrincipalName,        
        ticket          [5] Ticket,  <====== TGT        
        enc-part        [6] EncryptedData  
                                -- EncASRepPart or EncTGSRepPart,  
                                -- as appropriate  
}  
  
EncASRepPart    ::= [APPLICATION 25] EncKDCRepPart   
  
EncKDCRepPart   ::= SEQUENCE {  
        key             [0] EncryptionKey,  <======== Encrypted session key      
        last-req        [1] LastReq,  
        nonce           [2] UInt32,  
        key-expiration  [3] KerberosTime OPTIONAL,  
        flags           [4] TicketFlags,  
        authtime        [5] KerberosTime,  
        starttime       [6] KerberosTime OPTIONAL,  
        endtime         [7] KerberosTime,  
        renew-till      [8] KerberosTime OPTIONAL,  
        srealm          [9] Realm,  
        sname           [10] PrincipalName,  
        caddr           [11] HostAddresses OPTIONAL  
}  
  
LastReq         ::=     SEQUENCE OF SEQUENCE {  
        lr-type         [0] Int32,  
        lr-value        [1] KerberosTime  
}

ASREPRoast Attack

When pre-authentication is explicitly disabled for an account, an attacker can send an AS-REQ request for that user and receive a TGT along with an encrypted session key. The attacker can then crack the encrypted session key offline to recover the user’s password.

Golden Ticket

When an attacker obtains the KDC’s (krbtgt) long-term key, they can forge a Privilege Attribute Certificate (PAC) asserting membership in privileged groups. The attacker embeds this PAC in a forged TGT (a “Golden Ticket”), then uses the powerful forged TGT to request service tickets.

TGS-REQ

Ticket Granting Service Request: Sent by the client to the KDC to request access to a specific service. It includes the TGT obtained earlier and a new authenticator encrypted with the user-KDC session key.

Both the TGT and the authenticator sit in the padata field. The target SPN sits in the sname field of the req-body.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
TGS-REQ         ::= [APPLICATION 12] KDC-REQ  
  
KDC-REQ         ::= SEQUENCE {  
        -- NOTE: first tag is [1], not [0]  
        pvno            [1] INTEGER (5) ,  
        msg-type        [2] INTEGER (10 -- AS -- | 12 -- TGS --),  
        padata          [3] SEQUENCE OF PA-DATA OPTIONAL  <========= Authenticator + TGT  
                            -- NOTE: not empty --,  
        req-body        [4] KDC-REQ-BODY  
}  
  
KDC-REQ-BODY    ::= SEQUENCE {  
        kdc-options             [0] KDCOptions,  
        cname                   [1] PrincipalName OPTIONAL  
                                    -- Used only in AS-REQ --,  
        realm                   [2] Realm  
                                    -- Server's realm  
                                    -- Also client's in AS-REQ --,  
        sname                   [3] PrincipalName OPTIONAL,  <========= Target SPN  
        from                    [4] KerberosTime OPTIONAL,  
        till                    [5] KerberosTime,  
        rtime                   [6] KerberosTime OPTIONAL,  
        nonce                   [7] UInt32,  
        etype                   [8] SEQUENCE OF Int32 -- EncryptionType  
                                    -- in preference order --,  
        addresses               [9] HostAddresses OPTIONAL,  
        enc-authorization-data  [10] EncryptedData OPTIONAL  
                                    -- AuthorizationData --,  
        additional-tickets      [11] SEQUENCE OF Ticket OPTIONAL  
                                       -- NOTE: not empty  
}  

TGS-REP

Ticket Granting Service Response: Sent by the KDC to the client in response to a TGS-REQ.
It contains a service ticket and a new session key.

The TGS sits in the ticket field. The encrypted session key sits in the key field of the enc-part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
TGS-REP         ::= [APPLICATION 13] KDC-REP  
  
KDC-REP         ::= SEQUENCE {  
        pvno            [0] INTEGER (5),  
        msg-type        [1] INTEGER (11 -- AS -- | 13 -- TGS --),  
        padata          [2] SEQUENCE OF PA-DATA OPTIONAL  
                                -- NOTE: not empty --,  
        crealm          [3] Realm,  
        cname           [4] PrincipalName,  
        ticket          [5] Ticket,  <============ TGS        
        enc-part        [6] EncryptedData  
                                -- EncASRepPart or EncTGSRepPart,  
                                -- as appropriate  
}  

EncTGSRepPart   ::= [APPLICATION 26] EncKDCRepPart  
  
EncKDCRepPart   ::= SEQUENCE {  
        key             [0] EncryptionKey,  <=========== Encrypted session key
        last-req        [1] LastReq,  
        nonce           [2] UInt32,  
        key-expiration  [3] KerberosTime OPTIONAL,  
        flags           [4] TicketFlags,  
        authtime        [5] KerberosTime,  
        starttime       [6] KerberosTime OPTIONAL,  
        endtime         [7] KerberosTime,  
        renew-till      [8] KerberosTime OPTIONAL,  
        srealm          [9] Realm,  
        sname           [10] PrincipalName,  
        caddr           [11] HostAddresses OPTIONAL  
}  
  
LastReq         ::=     SEQUENCE OF SEQUENCE {  
        lr-type         [0] Int32,  
        lr-value        [1] KerberosTime  
}

Kerberoasting Attack

An attacker uses a valid TGT to request a service ticket (TGS) for a service principal name (SPN). The returned service ticket is encrypted with the service account’s password-derived key; the attacker can extract the ticket ciphertext and crack it offline to recover the service account’s password.

Silver Ticket

When an attacker obtains the long-term key of a service account, they can forge a service ticket (TGS) encrypted with that key. It will be accepted by the target service without contacting the domain controller, because the ticket is encrypted using the legitimate service account key. The forged ticket can include manipulated authorization data, such as group memberships, granting the attacker access to the service under the impersonated account.

AP-REQ

Application Request: Sent by the client to the target service to prove its identity and request access. It includes the TGS ticket and a fresh authenticator encrypted with the user-service session key.

1
2
3
4
5
6
7
8
9
10
11
12
AP-REQ          ::= [APPLICATION 14] SEQUENCE {
	   pvno            [0] INTEGER (5),
	   msg-type        [1] INTEGER (14),
	   ap-options      [2] APOptions,
	   ticket          [3] Ticket,
	   authenticator   [4] EncryptedData -- Authenticator  <======= Authenticator
}

APOptions       ::= KerberosFlags
	   -- reserved(0),
	   -- use-session-key(1),
	   -- mutual-required(2)

AP-REP

Application Reply: Sent by the service to the client in response to an AP-REQ to confirm mutual authentication. It contains a timestamp encrypted with the session key, proving that the service also possesses the shared key.

1
2
3
4
5
6
7
8
9
10
11
12
AP-REP          ::= [APPLICATION 15] SEQUENCE {
	   pvno            [0] INTEGER (5),
	   msg-type        [1] INTEGER (15),
	   enc-part        [2] EncryptedData -- EncAPRepPart
}

EncAPRepPart    ::= [APPLICATION 27] SEQUENCE {
	   ctime           [0] KerberosTime,
	   cusec           [1] Microseconds,
	   subkey          [2] EncryptionKey OPTIONAL,
	   seq-number      [3] UInt32 OPTIONAL
}
This post is licensed under CC BY 4.0 by the author.