This is a ticket-reading lab, not a Golden Ticket note. Target is a lab domain user on a joined VM. Goal: klist a TGT and a service ticket, write down authtime / start / end / renew-till, and name the checksum field I can see without decrypting. I do not mint tickets, I do not touch krbtgt hash, I do not pass /ptt.

1Figure 1. authtime is when AS succeeded. endtime is when the ticket dies. They are not the same field.
2AS-REP TGT  authtime/start/end/renew-till
3TGS-REP HTTP  end capped by TGT end; no 'initial' flag

Lab layout

1labs/krb_lab/
2  klist-tgt.txt
3  klist-http.txt
4  4768.json          # event log export, SIDs redacted

Account: labuser@LAB.INTERNAL. DC and workstation clocks NTP-synced. If they were not, the 401 at the bottom is the artifact.

Artifact: klist (Windows)

 1C:\lab> klist
 2Current LogonId is 0:0x[REDACTED]
 3
 4Cached Tickets: (2)
 5
 6#0>     Client: labuser @ LAB.INTERNAL
 7        Server: krbtgt/LAB.INTERNAL @ LAB.INTERNAL
 8        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
 9        Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent
10        Start Time: 3/14/2023 13:55:02 (local)
11        End Time:   3/14/2023 23:55:02 (local)
12        Renew Time: 3/21/2023 13:55:02 (local)
13        Session Key Type: AES-256-CTS-HMAC-SHA1-96
14        Cache Flags: 0x1 -> PRIMARY
15        Kdc Called: dc01.lab.internal
16
17#1>     Client: labuser @ LAB.INTERNAL
18        Server: HTTP/web.lab.internal @ LAB.INTERNAL
19        KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
20        Ticket Flags 0x40a10000 -> forwardable renewable pre_authent
21        Start Time: 3/14/2023 13:56:11 (local)
22        End Time:   3/14/2023 23:55:02 (local)
23        Renew Time: 3/21/2023 13:55:02 (local)
24        Session Key Type: AES-256-CTS-HMAC-SHA1-96
25        Cache Flags: 0
26        Kdc Called: dc01.lab.internal

Field decode I write next to the dump:

FieldTGT (#0)HTTP (#1)Meaning
Clientlabuser @ LAB.INTERNALsamethe principal the KDC authenticated
Serverkrbtgt/LAB.INTERNALHTTP/web.lab.internalSPN
Enc typeAES-256-CTS-HMAC-SHA1-96sameetype; RC4 here would be a finding
Flagsinitial, pre_authent, renewable, forwardableno initialinitial ⇒ this came from AS, not TGS
Start13:55:0213:56:11when the ticket becomes valid
End23:55:0223:55:0210h TGT lifetime; service ticket capped by TGT end
Renew3/21 13:55:02same7-day renew-till in this domain
Kdc Calleddc01.lab.internalsamewhich DC; compare to 4768

End on #1 equals End on #0. That is normal: a TGS ticket cannot outlive the TGT that requested it. A service ticket with end far beyond the TGT end, or a TGT with end far beyond domain policy, is the forgery-class anomaly — I file it as “times do not match policy”, I do not “fix” it by forging a better one.

Linux klist (same user, SSSD lab):

1$ klist
2Ticket cache: FILE:/tmp/krb5cc_[REDACTED]
3Default principal: labuser@LAB.INTERNAL
4
5Valid starting       Expires              Service principal
603/14/23 13:55:02    03/14/23 23:55:02    krbtgt/LAB.INTERNAL@LAB.INTERNAL
7        renew until 03/21/23 13:55:02
803/14/23 13:56:11    03/14/23 23:55:02    HTTP/web.lab.internal@LAB.INTERNAL

Same numbers, fewer flags. I still want the Windows dump when the question is PAC / etype.

Checksums, without decrypting a ticket

A Kerberos ticket is an encrypted blob plus some cleartext (realm, sname). Inside the enc-part: session key, times, flags, transited, authz-data (PAC on AD). The PAC carries its own checksums (ServerChecksum, KDCChecksum in Microsoft’s structure). From userland I do not dump those bytes. What I can see:

1# Wireshark, lab capture, AS-REP
2kerberos.CNameString            == labuser
3kerberos.realm                  == LAB.INTERNAL
4kerberos.ticket.sname           == krbtgt
5kerberos.etype                  == 18  (aes256-cts-hmac-sha1-96)
6kerberos.checksum.type          == 16  (hmac-sha1-96-aes256)   # authenticator cksum
7kerberos.authtime               == 2023-03-14 05:55:02 UTC
8kerberos.endtime                == 2023-03-14 15:55:02 UTC

kerberos.checksum.type on the authenticator is not the PAC KDC checksum. Do not mix them in the timeline. Authenticator checksum proves the client knew the session key for this AP-REQ. PAC KDC checksum is a DC-side integrity field; userland klist will not print it.

Event 4768 (AS success), redacted:

1Account Name:              labuser
2Supplied Realm Name:       LAB.INTERNAL
3Service Name:              krbtgt
4Service ID:                S-1-5-21-[REDACTED]-502
5Ticket Options:            0x40810010
6Ticket Encryption Type:    0x12          # AES256
7Pre-Authentication Type:   2             # encrypted timestamp
8Client Address:            127.0.0.1
9Certificate Issuer Name:   -

Match: klist Kdc Called dc01, etype AES256, client labuser, time 13:55:02 local = 05:55:02 UTC. That is a reconstructed AS. A 4768 with etype 0x17 (RC4) for this user is a separate ticket.

Analysis steps for a suspicious ticket

  1. Compare klist End/Renew to domain policy (Maximum lifetime for user ticket = 10 hours here, Maximum lifetime for user ticket renewal = 7 days).
  2. initial flag on a ticket whose Server is not krbtgt/... is odd.
  3. Etype RC4 (0x17) when the account has AES keys: hunt for constrained RC4 or an old client, not immediately “forged”, but file it.
  4. authtime in the future or far in the past vs DC clock: clock-skew or crafted times.
  5. Kdc Called empty / not a DC you own: local cache import. I still do not run /ptt to confirm.

Sanitized reproduction (clock skew / reject only)

I moved the workstation clock +10 hours once. AP-REQ to the lab HTTP SPN:

1C:\lab> curl -u : --negotiate http://web.lab.internal/who
2curl: (6)  /  HTTP/1.1 401 Unauthorized
3WWW-Authenticate: Negotiate
4
5# DC 4769 failure (excerpt)
6Result Code:               0x25  # KRB_AP_ERR_SKEW
7Account Name:              labuser
8Service Name:              HTTP/web.lab.internal
9Client Address:            10.[REDACTED]

0x25 skew is the crash analog. I set the clock back. I do not “fix” skew by minting a ticket with adjusted authtime.

Failed preauth (wrong password) is 4771, not a ticket:

1Event 4771  Kerberos pre-authentication failed
2Account Name:   labuser
3Pre-Auth Type:  2
4Failure Code:   0x18          # KDC_ERR_PREAUTH_FAILED
5Client Address: 127.0.0.1

No TGT in klist after that. Do not confuse 4771 with a checksum anomaly.

PAC times vs logon times

Event 4624 for the same logon (type 3 or 2) carries Logon Time that should sit within a few seconds of klist Start on the TGT. A 4624 at 13:55:02 and a TGT Start at 10:00:00 the previous day is a cache that survived a sleep, or a ticket that did not come from this logon. I record both clocks (UTC) before I say “forged”.

1# 4624 excerpt, same session
2Logon Type:                 2
3Authentication Package:     Kerberos
4Logon Time:                 2023-03-14T13:55:02.110
5Source Network Address:     127.0.0.1

Authentication Package: Kerberos plus a TGT in klist is consistent. NTLM plus a TGT from a different logon id (klist -li) is two stories; do not merge them.

Mitigation / policy I tick

  • AES only: msDS-SupportedEncryptionTypes on accounts, disable RC4 domain-wide when the audit is clean.
  • Ticket lifetimes: 10h / 7d is common; shorter for high-value. Log 4768 etype + options.
  • Clock: NTP on DCs and members. 0x25 should be rare.
  • Do not leave KRBTGT password unrotated; rotation is an ops note, not a forge recipe. I record last set time from a privileged query I do not paste.
  • Detection: TGT end > policy; service ticket with initial; etype 0x17; 4768 from a workstation that has no corresponding logon 4624.

What I file after this lab

  • klist: TGT AES256, flags initial|pre_authent|renewable|forwardable, start 13:55:02, end +10h, renew +7d
  • HTTP ticket: no initial, end equal to TGT end
  • Wireshark: kerberos.etype==18, checksum.type==16 on authenticator, times UTC
  • 4768 etype 0x12, preauth 2, address 127.0.0.1
  • Skew repro: 401 + 4769 0x25; bad password: 4771 0x18
  • Out of scope: forging PAC checksums, krbtgt hash, /ptt

Commands appendix

1klist
2klist -li 0:0x[REDACTED]
3# Linux: klist; kvno HTTP/web.lab.internal
4wevtutil qe Security /q:"*[System[(EventID=4768)]]" /c:1 /f:text