Charlie Clark

While helping Andrew Schwartz with his Kerberos FAST post (which has more information about what FAST is and how it works, so have a read), I noticed something interesting. AS-REQs for machine accounts are unarmored. Kerberos armoring is described by Microsoft:

Kerberos armoring uses a ticket-granting ticket (TGT) for the device to protect authentication service exchanges with the KDC, so the computer’s authentication service exchange is not armored. The user’s TGT is used to protect its TGS exchanges with the KDC.

This made me wonder whether it was possible to request service tickets (STs) from the authentication service (AS). The ability to request STs from the AS has several consequences, including new attack paths, detection bypasses, and potential weakening of security controls. All the issues discussed in this post were reported to Microsoft and were “considered to be by design” (Figure 1).

Related reading

Kerberos recap

First, here’s a high-level overview of the typical Kerberos flow (Figure 2, sourced from ADSecurity):

  1. An account requests a TGT from the domain controller (DC).
  2. The DC responds with a TGT, which has its own session key.
  3. The TGT and its session key are used to request a service ticket (ST) from the DC.
  4. The DC responds with an ST, which has its own session key.
  5. The ST and its session key are used to authenticate against the end service.
  6. The end service either grants or prohibits access.
Figure 2. Typical Kerberos flow (AD Security), illustrating the steps in the previous list
Figure 2. Typical Kerberos flow (ADSecurity)

The fact that a session key is issued for each ticket is an important feature for the following research. This session key is passed back to the requesting account within an encrypted section of the response; the encryption key is already known to the requestor.

For instance, the TGT session key is stored within a section that is encrypted with the key used to prove the requestor’s identity when requesting a TGT. This key is normally the long-term key (password hash) of the account. But in the case of Public Key Cryptography for Initial Authentication (PKINIT) in the Kerberos protocol, the key is derived from the certificate. The ST session key is stored within a section that is encrypted with the TGT session key.

The ticket session key is required to use the ticket in the next step of the Kerberos flow.

A Kerberos request has two main sections:

  • padata (pre-authentication data)
  • req-body (request body)

The req-body is sent mostly in plaintext and contains several pieces of information:

  • kdc-options: various options
  • cname: name of the requesting account (optional)
  • realm: domain name
  • sname: service principal name (SPN) for the resulting ticket (optional)
  • from: time from which the client wants the ticket to be valid (optional)
  • till: time until which the client wants the ticket to be valid
  • rtime: the requested renew time (optional)
  • nonce: random number
  • etype: list of supported encryption types of the client
  • addresses: list of addresses of the requesting client (optional)
  • enc-authorization-data: various authorization data sections, encrypted with the session key that is usually used for local privileges (optional)
  • additional-tickets: list of tickets required for the request (optional)

A Kerberos reply has several sections and contains an encrypted part:

  • pvno: version number
  • msg-type: type of message (11 AS, 13 TGS)
  • padata: pre-authentication data (optional)
  • crealm: client domain name
  • cname: name of the requesting account
  • ticket: resulting ticket
  • enc-part: encrypted data for use by the client

The issue with AS requested service tickets

The part of the Kerberos flow that this post focuses on is AS-REQ/AS-REP, which is usually used to request a TGT. In normal operations, an AS-REQ has one of two values within its sname field inside the req-body:

  • krbtgt/domain.local: used to request an initial TGT
  • kadmin/changepw: used to request a short-lived ticket, which can be used to reset passwords using a KRB-PRIV message (defined in RFC 3244)

I noticed that with Kerberos Flexible Authentication Secure Tunneling (FAST) enforced, machine accounts still sent their AS-REQs unarmored. I wondered whether an AS-REQ could be used to request an ST directly, rather than a TGT. This caused me to modify Rubeus to determine whether specifying another SPN within the sname of an AS-REQ would cause the DC to reply with an ST for that SPN. As it turns out, the answer was “yes” (Figure 3).

Figure 3. Screenshot of an AS requested ST
Figure 3. Service ticket requested from the AS

By using a machine account, I can request an ST without using armoring when FAST is enforced. What else is possible?

New ways to Kerberoast

Kerberoasting, discovered by Tim Medin, is a method to recover the plaintext password or NT hash for a service account, generally a user account with an SPN. Kerberoasting is possible because part of an ST is encrypted with the service account’s long-term key (password hash). By extracting the encrypted part of the ticket, it is possible to form a hash from various cleartext passwords and attempt to decrypt the encrypted part. If decryption is successful, then the hash used is the long-term key used to encrypt the ticket. That key can then ultimately be used to authenticate as the service account.

Furthermore, any account can request an ST for any service. Therefore, the ability to authenticate to Active Directory (AD) is required to perform the attack. At least, that used to be true.

Kerberoasting without pre-authentication

First, I tried to use an account that did not require pre-authentication (DONT_REQ_PREAUTH) to request an ST. When an account does not require pre-authentication to authenticate, a TGT can be requested without requiring pre-authentication data, which is encrypted with some form of credential (e.g., password hash, certificate). If an attacker has not obtained a valid credential for an account, valid pre-authentication cannot be generated. If pre-authentication is not required, this is not an issue.

When a ticket is requested without pre-authentication, the result still includes an encrypted part. This encrypted part is encrypted with the credential key used for authentication and contains the session key for the ticket included within the reply. This is the encrypted data used in the ASREPRoast attack by Will Schroeder. The resulting TGT is usable only with access to the requesting accounts key, since the TGT session key is required.

However, for Kerberoasting, access to the session key is not required. Only the resulting ST—or more accurately, the encrypted part of the ST, which is not secured with the requesting accounts key—is required. Therefore, if any account is configured to not require pre-authentication, it is possible to Kerberoast without any credentials. This method of Kerberoasting has been implemented in Rubeus within this PR.

Demonstration

Because access to a valid account has not yet been achieved, LDAP cannot be queried. Instead, a list of potential service accounts is required. Previous research by Arseniy Sharoglazov shows that STs can be requested using only the username of the service account rather than requiring the actual SPN—very useful for this research.

A list of usernames can be generated in several ways, including user enumeration using null sessions on a DC, generating a list of usernames using open-source intelligence (OSINT), or guessing potential usernames. Any list of potential usernames can be easily verified by sending an AS-REQ without pre-authentication. A valid username that requires pre-authentication receives a KDC_ERR_PREAUTH_REQUIRED error (Figure 4).

Figure 4. Screenshot showing an AS-REQ without pre-auth for a valid username that requires pre-auth
Figure 4. User requires pre-authorization

A valid username that does not require pre-authentication receives a TGT (Figure 5).

Figure 5. Screenshot showing response for a user that does not require pre-auth
Figure 5. User does not require pre-authorization

An invalid username receives a KDC_ERR_C_PRINCIPAL_UNKNOWN error (Figure 6).

Figure 6. Response for an invalid username
Figure 6. User does not exist

For demonstration purposes, a list is generated using a null session on the DC, using enum4linux-ng’s RID cycling method (-R), as Figure 7 shows.

Figure 7. Screenshot showing generated list
Figure 7. enum4linux-ng RID cycling

Using this list of usernames, determining accounts that do not require pre-authentication is easy in AD (Figure 8).

Figure 8. Output of a scan for accounts that do not require pre-auth
Figure 8. Scan for accounts not requiring pre-authentication

Note that AS-REQs without pre-authentication are not logged as a Windows event unless the account does not require pre-authentication.

With the list of usernames and the username of an account that does not require pre-authentication, the attack can be launched (Figure 9).

Figure 9. Screenshot showing Kerberoasting without pre-auth
Figure 9. Kerberoasting without pre-authorization

The resulting output can then be used to attempt offline password cracking.

Proof of concept: RoastInTheMiddle

Another interesting consequence is the ability to Kerberoast from a Man-in-the-Middle (MitM) position. This type of attack generally is not possible with TGS-REQs because the optional cksum field within the authenticator inside the AP-REQ protects the req-body of the request and is frequently included by genuine Windows Kerberos clients. Therefore, modifying the sname of a TGS-REQ without updating the checksum within the authenticator invalidates the authenticator checksum and returns a KRB_AP_ERR_MODIFIED error. But this is not a problem for AS-REQs because the req-body, and consequently the sname field, are not protected.

While testing this approach, I discovered that AS-REQs can be replayed many times. An attacker needs to capture only one AS-REQ to send a lot of AS-REQs with different sname values.

Demonstration

To demonstrate this approach, I wrote a rough proof of concept (POC). This POC, RoastInTheMiddle, implements an ARP spoof between DCs and victim systems to perform an MitM attack. The POC then passes traffic through while listening for AS-REQs. When an AS-REQ is found, the POC performs a Kerberoast. The POC is not attack-ready but demonstrates that an attack is possible.

First, the POC starts four threads, a sniffer, an ARP spoofer, a re-assembler (for requests that are split across multiple packets), and the roaster (Figure 10).

Figure 10. Screenshot showing the RoastInTheMiddle POC starting
Figure 10. RoastInTheMiddle starting up

When it sees an AS-REQ, the POC starts trying to Kerberoast the supplied list, which can contain usernames or SPNs (Figure 11).

Figure 11. Screenshot showing POC Kerberoasting
Figure 11. RoastInTheMiddle Kerberoasting

As Figure 11 shows, this attempt results in any received STs being output in hashcat format, ready for offline password cracking.

The ability to MitM AS-REQs, then modify and replay them, might also be useful in developing other attacks. I attempted to modify the kdc-options to include the proxiable flag, which results in a ticket with the proxiable flag set. However, I was unable to find an attack path using that ticket and flag. This behavior might also enable the use of other accounts to perform a Kerberoast, enabling attackers to avoid burning a compromised account.

Improvements

Some improvements might be possible for this process. First, it is possible to coerce an AS-REQ from a TGS-REQ by intercepting it and replying with a KRB_AP_ERR_BAD_INTEGRITY error. Doing so forces the client to reauthenticate by sending an AS-REQ.

It should also be possible to perform this attack using DHCPv6 nameserver injection (like mitm6 by Dirk-jan Mollema or Inveigh by Kevin Robertson), responding to SRV DNS queries for the LDAP service and then dealing with the following LDAP connection.

Support for modifying the etypes within the request enables encryption type downgrade attacks when the environment allows, as described by Will Schroeder here.

Lastly, the POC requires the installation of Npcap on the system running the POC (which uses sharppcap), primarily for ARP spoofing. If you take the IPv6 route or implement the ARP replies by using raw sockets, you can remove this dependency.

Bypassing detections

Many Kerberos detections rely on 4769 events (A Kerberos service ticket was requested). However, requesting a service ticket using an AS-REQ does not produce 4769 events but rather 4768 events (A Kerberos authentication ticket (TGT) was requested).

Figure 12 shows a 4768 event when an ST is requested using an AS-REQ.

Figure 12. Image of event 4768
Figure 12. Event 4768 for a service ticket

Therefore, attackers using this method can easily circumvent many detections that rely on 4769 events.

Other consequences of AS requested service tickets

Although I was unable to request S4U2self tickets from the AS, STs retrieved from the AS lack the Ticket Checksum (brought in to protect S4U2self tickets against the bronze bit attack by Jake Karnes).

Lastly, an ST requested from the TGS is generally returned with a PAC (Figure 13).

Figure 13. Screenshot of ST (with PAC) request from the TGS
Figure 13. Requesting an ST with a PAC from the TGS

It is possible to request an ST without a PAC from the TGS, but doing so requires changing the service accounts NO_AUTH_DATA_REQUIRED bit in the useraccountcontrol attribute (Figure 14).

Figure 14. Output showing attribute
Figure 14. useraccountcontrol attribute for SDC1 and pgreen

When this configuration is in place, the returned ST lacks a PAC, as shown by the difference in size of the returned ticket (Figure 15).

Figure 15. Screenshot of ST (without PAC) request from TGS
Figure 15. Requesting an ST without a PAC from the TGS

An ST without a PAC can be requested from the AS simply by setting the PA-PAC-OPTIONS PA data section to false by adding the /nopac switch to Rubeus (Figure 16).

Figure 16. Output showing ST request (without a PAC) from the AS
Figure 16. Requesting an ST without a PAC from the AS

This approach might be used as an alternative to creating silver tickets, by requesting an ST without a PAC, then injecting another PAC by including it within the enc-authorization-data section of the request. It might also provide other potential attack paths.

Detection of AS requested service tickets

Because Microsoft apparently does not find these issues worth fixing, detection from within your organization is the only option. As shown previously, when an ST is requested from the AS, event 4768 is logged (Figure 17).

Figure 17. Screenshot of event 4768
Figure 17. Event 4768 for a service ticket

In this event, you can see that the Service Name and Service ID are not krbtgt. All genuine tickets requested from the AS, including kadmin/changepw tickets, have a Service Name and Service ID of krbtgt (Figure 18).

Figure 18. Screenshot showing normal event 4768
Figure 18. Normal event 4768

Checking network traffic for AS-REQs that are not for the krbtgt/domain or kadmin/changepw should also detect these requests (Figure 19).

Figure 19. Screenshot of AS-REQ ST request in Wireshark
Figure 19. AS-REQ ST request in Wireshark

This research, along with Microsoft’s response, demonstrates the need for continuous monitoring and proper hardening measures. The ability to circumvent current detections and perform effective attacks, like Kerberoasting, from an unauthenticated position is a serious issue that should not be ignored. The research described here could lead to further novel attacks, potentially putting organizations at higher risk.

Ensure that detections are in place when these types of ticket requests are made.

Acknowledgements

I’d like to that the following people for their contributions to this research:

Timeline

  • May 25, 2022: Reported to MSRC
  • May 27, 2022: MSRC changed status to Review/Repro
  • July 13, 2022: MSRC responded that the behavior was “by design”
  • September 27, 2022: Public disclosure

Learn more from Semperis Research