Kerberos
0. TL;DR
Download Kerberos assets
1. Whats Kerberos and Why Kerberos Exists
Kerberos was designed at MIT in the late 1980s, with the first public release (v4) in 1989. It was built to provide secure authentication for client–server applications in an open network environment.
The protocol is named after Cerberus (also spelled Kerberos), the three-headed guard dog of Hades in Greek mythology. Just as Cerberus guards the entrance to the underworld, Kerberos is meant to guard access to network services. The three heads map loosely to the main parties in the authentication flow:
- the client ,
- the server, and
- the trusted third party (the KDC) that issues and validates tickets
Before Kerberos, there was NTLM (NT LAN Manager). It’s Microsoft’s legacy challenge–response authentication protocol. It predates Kerberos in Windows environments, can authenticate local logons without involving a domain controller, and still lingers in a lot of networks even though Microsoft has been trying to deprecate it for years.
How it works, in rough terms: the client says “I want to authenticate,” and the server sends back a random challenge. The client encrypts that challenge using a hash derived from the password (the NT hash) and sends the response. The server (or the domain controller, for domain accounts) performs the same computation and checks if the values match. No password is sent over the wire—just proof that you know the hash.
The problem is relaying. Depending on the protocol in use and whether protections like SMB signing, LDAP signing, or Extended Protection for Authentication are enforced, an attacker in the middle can forward that challenge–response exchange to another server and get authenticated as you, without ever cracking the hash.
with Kerberos, instead of proving who you are separately to every service you touch, you prove it once to the Key Distribution Center which then issues tickets that other services accept. Your password never travels across the network, not even as a simple hash in the way NTLM uses it.
This tripartite design is what gives Kerberos its stronger security properties compared to NTLM, including mutual authentication and support for delegation.
2. The Players
Before all, you need to know that Kerberos loves acronyms and if you don’t have these memorized cold the rest of this post is gonna be complicated to understand.
| Actor | Role |
|---|---|
| Client | You, me, the user trying to reach a service on the network |
| KDC (Key Distribution Center) | The trusted authority. Stores account secrets (password-derived keys) and issues/verifies tickets. On AD this runs on every Domain Controller. |
| AS (Authentication Server) | A role inside the KDC. Handles the very first exchange between client and KDC. |
| TGS (Ticket Granting Server) | Another role inside the KDC. Hands out tickets for specific services once you’ve already proven yourself to the AS. |
| Service Server | Whatever you’re actually trying to reach, file server, web app, SQL instance, doesn’t matter. |
Yeah, AS and TGS both live inside the KDC. In practice on a Windows domain the KDC service on your DC just wears two hats depending on which request it receives.
Note
The krbtgt account is the actual secret backbone here, its password-derived key is what encrypts every TGT. If that key leaks, we’re talking Golden Ticket territory, more on that later.
The whole thing happens in three major exchanges :
Client <---> KDC : AS-REQ / AS-REP (get a TGT)Client <---> KDC : TGS-REQ / TGS-REP (get a Service Ticket)Client <---> Service : AP-REQ / AP-REP (actually use the service)Important
You can see AS and AS, both the same acronym, meaning something different depending on the context. Same for TGS and TGS.
AS alone means Authentication Server
AS in AS/REQ-REP means Authentication Service
TGS alone means Ticket Granting Server
TGS in TGS/REQ-REP means Ticket Granting Service
Lessgo, one exchange at a time.
3. AS-REQ / AS-REP
AS-REQ
Here the client tells the AS “I’m this user, give me a TGT (Ticket Granting Ticket)”.
If pre-authentication is enabled (and on a modern domain it should be, always), the client can’t just claim an identity for free. It has to prove it right there in the request by encrypting the current timestamp with a key derived from its own password and attaching it.
Without Preauth :
AS-REQ: cname = mohamed realm = MG.LOCAL sname = krbtgt/MG.LOCALWith Preauth :
AS-REQ: cname = mohamed realm = MG.LOCAL sname = krbtgt/MG.LOCAL padata = Encrypted timestamp with client's keyThe KDC receives this, and using the long-term key it already has stored for that account (derived from the password when it was set), it tries to decrypt the timestamp.
Note
If pre-auth is disabled on an account, anyone can request an AS-REQ for that username with no proof at all, and the KDC will just hand back an AS-REP encrypted with that account’s key. Attackers grab this and try to crack it offline. That’s what AS-REP Roasting is, and we’ll get back to it in section 8.
AS-REP
If AS-REQ is valid, the KDC replies with two things bundled together:
AS-REP: TGT Session_Key_client-kdcThe TGT is encrypted with the krbtgt’s account key, and it contains :
- a session key,
- the client identity,
- the group memberships (PAC),
- validity times
Since its encrypted with krbtgt’s account key (Unknown by client) the client can’t decrypt this. Never. He will just use it as it is.
The Session_Key_client-kdc at the opposite, is encrypted with clients password-derived key, hence this is th only part in the AS-REP, he can, and will actually read its content.
So at the end of this exchange the client is holding:
- An opaque TGT it can’t read
- A session key it can read, used for the next step
4. TGS-REQ / TGS-REP - Trading the TGT for Access
Now the client wants to actually reach something, say a file share. It goes back to the KDC, but this time talks to the TGS role specifically.
TGS-REQ
TGS-REQ: padata: PA-TGS-REQ = AP-REQ(TGT, Authenticator) sname = cifs/fileserver01.corp.localThe TGT and Authenticator are packaged together as an AP-REQ. Why ? cuz in kerberos proving yourself to the TGS works exactly like proving yourself to any other service, except the “service” happens to be the TGS role of the KDC. sname sits outside that padata, it’s just telling the KDC which service you actually want a ticket for.
The Authenticator inside it is encrypted with the session key you got in the AS-REP. Inside it:
- your identity (cname)
- a current timestamp
Only you and the KDC know that session key (remember, it was inside the part of the AS-REP only you could decrypt). So when the KDC decrypts this Authenticator using the copy of the session key it kept sealed inside your TGT, and gets back a timestamp that’s recent and an identity that matches the TGT, it knows for certain the request came from whoever the TGT actually belongs to, not just someone who stole the TGT off disk and replayed it.
The KDC decrypts the TGT with its own krbtgt key, pulls the session key back out of it, uses THAT to verify the authenticator matches.
TGS-REP
If everything is correct again, the KDC issues:
TGS-REP: Service_Ticket Session_Key_client-serviceThe Service Ticket is encrypted with the target service’s own long-term key (derived from the service account’s password, or the machine account key for computer objects), so you can’t read that one either. Inside it:
- client’s identity (cname),
- group memberships (PAC)
- the new session key,
The same session key in the Service ticket is also given separately, and it can be decrypted by the client since its encrypted with the Session_Key_client-kdc got from AS-REP.
5. AP-REQ / AP-REP
Now, finally, the client walks up to the actual service and presents its credentials directly, no KDC involved this time.
AP-REQ
AP-REQ: Service_Ticket AuthenticatorThe service decrypts the Service Ticket with its own long-term key (which it has locally), pulls out the session key, checks if the authenticator was encrypted with that exact key and has a fresh timestamp.
If it valid, the service now knows two things: this really is the client the ticket says it is, and the request is recent (not a replay of something captured hours ago).
AP-REP (optional)
If Mutual Authentication is requested, the service proves its identity back to the client:
AP-REP: Encrypted client's timestampThe service doesn’t just echo your timestamp back encrypted, that’d be too easy to replay. The AP-REP contains the client timestamp from the authenticator, encrypted with the client–service session key. The client verifies that it matches the timestamp it originally sent, proving that the service decrypted and processed the authenticator.
This matters more than people give it credit for. Without mutual auth, the client has zero guarantee it’s not talking to a rogue/spoofed service. AP-REP closes that gap, both sides now trust each other, and both sides share key material they could use to encrypt/sign the rest of the conversation if the application layer wants that.
6. Keys Cheat Sheet
Honestly this is the table I wish existed the first time I learned this, because the “who encrypts what with which key” part is where i got lost the most
| Key | Derived from | Used to encrypt |
|---|---|---|
Key_client | Client’s password hash | Pre-auth timestamp (AS-REQ), Session_Key_client-kdc (AS-REP) |
Key_krbtgt | krbtgt account password hash | The TGT itself |
Session_Key_client-kdc | Random, generated by KDC | Authenticator in TGS-REQ, Session_Key_client-service in TGS-REP |
Key_service | Service/machine account password hash | The Service Ticket |
Session_Key_client-service | Random, generated by KDC | Authenticator in AP-REQ, AP-REP |
One nuance tho, Key_client in the table above isn’t always the NT hash. The actual long-term key depends on the negotiated encryption type:
- RC4 uses the NT hash directly,
- AES derives the key differently, via PBKDF2 over the password and salt.
AES is generally preferred and widely available on modern domains, but RC4 can still get negotiated for compatibility
Notice your password (or rather, the key derived from it) only gets used once, right there in that first AS exchange, to encrypt the pre-auth timestamp and unwrap your session key. Every exchange after that runs on randomly generated session keys and long-term keys you never touch again.
7. The PAC
Nothing in the base Kerberos spec carries your group memberships, your SID, or your privileges. Kerberos authenticates identity, that’s it.
That’s a problem in AD, where “what you’re allowed to do” is exactly what services need to know. So Microsoft bolted on an extension, the PAC (Privilege Attribute Certificate). It rides inside your TGT and your Service Tickets, and it’s basically your ID card’s fine print, your SID, your group memberships, everything a service needs to decide what you can access.
When the KDC builds your TGT, it signs the PAC with the krbtgt. Later, when the TGS hands you a Service Ticket, it re-signs the PAC with the target service’s own key too. So by the time the PAC reaches a service, it’s been signed twice, once by the KDC (proving it came from a legitimate source), once by the TGS on behalf of the service (proving it wasn’t tampered with in transit).
this would deserve a whole post to detail it but i chosed to simplify it to not lose you, my beloved readers <3 :)
Note
This is also why a Golden Ticket is so dangerous cuz since we’re forging it with the actual krbtgt key, we’re passing it legitimately, since we hold the same key the real KDC would’ve used. The PAC stuffed in there (fake group memberships, fake SID history, Domain Admins if you want) signs perfectly clean.
Diamond Ticket and Sapphire Ticket both exist to dodge Golden Ticket detection heuristics (unusual ticket lifetimes, missing pre-auth flags), but they get there differently:
- Diamond Ticket starts from a real TGT and patches the PAC in place, adding fake group SIDs (
Domain Admins, say), then re-signs with the stolen krbtgt key. The ticket metadata is legitimate, the group memberships inside it aren’t, exactly what PAC-vs-AD cross-referencing is built to catch. - Sapphire Ticket goes further: instead of fabricating memberships, it obtains a real PAC belonging to an actual privileged account (via an S4U2Self+U2U trick) and swaps that PAC into the ticket wholesale. Since the memberships are genuine, cross-referencing against AD won’t flag anything, making it the harder of the two to detect.
8. Timing Is Everything
Two details from the diagram that are easy to skip past but actually carry most of Kerberos’s replay protection:
Clock skew tolerance. The pre-auth timestamp (and every Authenticator after it) has to fall inside a tolerance window around the KDC’s clock, 5 minutes by default on AD. This is exactly why domain-joined machines are so picky about time sync, if your client drifts more than 5 minutes from the DC, authentication just breaks.
Ticket lifetime. TGTs and service tickets both have finite lifetimes, commonly 10 hours by default. TGTs specifically may be renewable, commonly up to 7 days (MaxRenewAge), subject to domain and ticket-policy settings, that renewal window doesn’t apply identically to service tickets. This limits the blast radius if a ticket gets stolen, an attacker with a captured TGT doesn’t get forever, they get whatever’s left on the clock.
Session key uniqueness. The KDC normally generates fresh session keys for newly issued credentials. Reusing an old client-service session key across sessions would let someone replay an old Authenticator.
9. Attack Surface
Kerberos is solid crypto-wise, but that doesn’t mean “unattackable”, most real-world Kerberos attacks target the trust chain and the key material, not the math. I’m not gonna hand you full exploitation walkthroughs here, cuz that’s a post of its own (or five), but you should at least recognize these names because they all map directly back to the steps above :
- AS-REP Roasting : targets accounts with pre-auth disabled. No proof needed to get an AS-REP, so you just request it and crack the
Key_client-encrypted portion. - Kerberoasting ; any authenticated user can request a Service Ticket (TGS-REQ) for any service with a registered SPN. That ticket is encrypted with
Key_service, which is derived from the service account’s password. Weak service account password = crackable, no interaction with the DC needed after the initial request. - Golden Ticket : if the krbtgt key itself gets compromised, an attacker can forge TGTs from scratch, for any user, with any group membership, valid until someone rotates that key (twice, because of the password history)
- Silver Ticket : same idea but scoped to a single service, forge a Service Ticket using the target service account key. Its practical success depends on the target service’s PAC validation behavior and the applicable PAC signature requirements; it may work against services that do not perform strong DC-side validation, and its not universally equivalent to a legitimate KDC-issued ticket
- Pass-the-Ticket : steal a valid TGT or Service Ticket out of memory (LSASS) and replay it from another machine, no password needed at all.
- Overpass-the-Hash / Pass-the-Key - use a stolen NTLM hash or AES key directly as
Key_clientto request a legit TGT, skipping the password entirely.
Every single one of these abuses a step in the diagram above, that’s the whole point of actually understanding the protocol instead of memorizing attack names.
Here are the sources i used to lean about the protocol, i suggest diving into the RFC since its the most accurate source of truth here :
- https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/ae60c948-fda8-45c2-b1d1-a71b484dd1f7
- https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/kerberos-protocol-registry-kdc-configuration-keys
- https://datatracker.ietf.org/doc/html/rfc4120
- https://www.manageengine.com/products/active-directory-audit/learn/kerberos-vs-ntlm.html
