Kerberos Unlocked (Part 3): Interacting With Services

In the previous post, we covered how the client receives a Service Ticket in the TGS-REP. With this ticket in hand, the client can now authenticate to the specific service it was issued for. The service, in turn, can decrypt the Service Ticket using its own long-term key and verify the client’s identity. This article covers how the client interacts with the service.

Here is how the client in interacts with the service (step by step below)


AP-REQ

The AP-REQ message sent to a service contains two parts: some service-specific data (unique to the service being accessed) and the ap-reqsection, which carries the Service Ticket and an Authenticator. Hence, the ap-req section prove the client’s identity to the service.

The exact placement of the ap-req section within the overall request can vary depending on the service implementation. Since the client is talking directly to the service, each service communicates differently and parses Kerberos data in its own way, which means the ap-req section may appear in different places within the overall request.

What doesn’t change, however, is the internal structure of the ap-req section itself. It is always the same and always critical for authentication, because it contains the Service Ticket and the Authenticator. Without these, Kerberos authentication would not be possible.

This photo shows how the position of the ap-req section can vary between services:

We’ll focus only on the ap-req section, since it’s the part responsible for Kerberos authentication. Everything else in the message is service-specific and can vary depending on the protocol (SMB, LDAP, HTTP, etc.), but the ap-req structure itself remains the same.

This is how the ap-req section is structured (sent over the network to the service):

  1. pvno This field is included in each message, and specifies the protocol version number (which is just 5).
  2. msg-type → This field indicates the type of a protocol message.
  3. ap-options → This field is a collection of bit flags that let the client tell the KDC or a service how it wants the authentication to be handled. [EXPLAINED BELOW]
  4. ticket → This is the Service Ticket we received in TGS-REP and we provide it to the service to verify our identity.
  5. Authenticator → At its core, the Authenticator contains the client’s identity (name and domain) and the current timestamp, all encrypted with the session key. Each Authenticator is freshly generated at the time of the request, ensuring it’s unique. This mechanism prevents replay attacks, since the service will reject it if the timestamp isn’t within the allowed window(usually ~5mins). (We covered this in detail in the previous article.)
Visual representation of the ap-req section:
Here is how it looks like in Wireshark (an request to the LDAP Service):

ap-options

This field can carry three flags: use-session-key , mutual-required and reserved (the reserved flag is reserved for later use and serves no purpose). Each flag is a simple boolean — they can be set independently, so either one, both, or neither may be true.

Here is how it looks like in Wireshark:

The use-session-key flag is set to true in special cases (like delegation). Normally, a Service Ticket is encrypted with the service account’s long-term key, so only the service can decrypt it. But with this flag, the ticket provided is instead encrypted using the session key that the KDC shares with the service (from the service’s own TGT). This means the service uses its existing session key to read the ticket, rather than its long-term key. In practice, this flag is mostly false and is rarely needed outside of advanced scenarios like user-to-user authentication. (NOT IMPORTANT FOR US AT THIS STAGE AND RARELY USED)

The more important option to understand here is the mutual-required flag. When this flag is set, the client is essentially telling the service: "‘I’ve proven I’m a legitimate client by sending you my Service Ticket and Authenticator — now you prove that you’re the real service and not an attacker in the middle."

If this flag is true (which depends on the service if its true or not, but it mostly is), the service must reply with an AP-REP message. This response proves the service's identity back to the client, and only then will the client fully trust the service and start the session.

💡
See below how the service proves itself to the client.

If the flag is false (not default), the service won’t send back an AP-REP, and the client will go ahead and start the session without requiring the service to prove itself.


AP-REP

This is the service’s response when the client sets the mutual-required flag in the ap-options.

The exact placement of the ap-rep section within the overall request can vary depending on the service implementation(just like in ap-req).

💡
It is [EXPLAINED BELOW] in detail.

This is how the ap-rep section is structured (sent over the network to the client):

  1. pvno This field is included in each message, and specifies the protocol version number (which is just 5).
  2. msg-type → This field indicates the type of a protocol message.
  3. enc-part → Encrypted with the Service Session Key:
    1. ctime → This field contains the timestamp that the client sent in the Authenticator (in AP-REQ).
    2. cusec → This field contains the microsecond part of the client's timestamp that the client sent in the Authenticator (in AP-REQ).
    3. subkey → This field lets the service propose a new encryption key to use for securing messages. (not important right now will cover later)
    4. seq-number → This is a random starting value chosen by the service and sent to the client. From then on, each new message (application messages after the AP-REQ and AP-REP) increments the value by one. This allows both the client and the service to track the order of messages and detect replay attacks — since an attacker trying to reuse an old message would present an already-used sequence number.
Visual representation of the ap-rep section:
Here is how it looks like in Wireshark (an response from the LDAP Service):

What does this AP-REP do?

In simple terms, the service takes the timestamp that the client included in the Authenticator (inside the AP-REQ), decrypts it with the Service Session Key, and then re-encrypts the same timestamp (the timestamp client sent in the Authenticator) with that same Service Session key before sending it back to the client in the AP-REP.

When the client receives the AP-REP, it decrypts the timestamp using its own copy of the Service Session Key and compares it to the one it originally sent (in the Authenticator in AP-REQ request). If the values match, the client knows the service is genuine — because only the real service could have decrypted the Authenticator and re-encrypted same the timestamp.

This mechanism ensures mutual authentication: not only does the service know who the client is (from the AP-REQ), but the client can also verify that it’s talking to the legitimate service, not an attacker.


I’ve kept this post short and focused so it’s easier to digest. In the upcoming parts, we’ll see what a PAC is, and the different ways Kerberos can be attacked.

I’d really appreciate your feedback and thoughts — they’ll help me improve as I continue this series.

https://x.com/beacon_bytes