SPN-jacking: An Edge Case in WriteSPN Abuse

By Elad Shamir February 10, 2022 | Active Directory

Some people are a hammer in search of a nail, but I’m a hammer in search of Kerberos delegation. So, when I heard that a WriteSPN edge was introduced to BloodHound 4.1, I started exploring alternative abuse techniques beyond targeted Kerberoasting, and I found an edge case (pun intended) that can be chained together with Kerberos Constrained Delegation.

Tl;dr

Suppose an attacker compromises an account set for Constrained Delegation but doesn’t have the SeEnableDelegation privilege. The attacker won’t be able to change the constraints (msDS-AllowedToDelegateTo). However, if the attacker has WriteSPN rights over the account associated with the target SPN, as well as over another computer/service account, the attacker can temporarily hijack the SPN (a technique called SPN-jacking), assign it to the other computer/server, and perform a full S4U attack to compromise it.

Also, if the target SPN is not currently associated with any account, the attacker can appropriate it similarly.

I’ll be the first to admit this is not a groundbreaking discovery, but it can revive seemingly dead-end attack paths under particular circumstances. SPN-jacking can also be an alternative takeover technique if RBCD or Shadow Credentials are not viable.

Kerberos delegation primer

Kerberos delegation is a mechanism that allows services to impersonate users to other services. For example, a user may access a front-end application, and that application may, in turn, access a back-end API with the user’s identity and permissions.

Kerberos delegation comes in three flavors: Unconstrained Delegation, Constrained Delegation, and Resource-Based Constrained Delegation (RBCD).

Unconstrained Delegation

Unconstrained Delegation requires users to send their ticket-granting-ticket (TGT) to the front-end service (Server A). Then the front-end service can use that ticket to impersonate the user to any service, including the back-end service (Server B).

Constrained Delegation

Constrained Delegation allows the front-end service (Server A) to obtain Kerberos service tickets for users to a predefined list of services specified by their Service Principal Name (SPN), such as the back-end service, Server B.

Note that Constrained Delegation allows the service to impersonate users out of thin air, whether they authenticated to the service or not. Many think that it depends on the configuration of the TrustedToAuthForDelegation attribute. However, when chained with Resource-Based Constrained Delegation, that limitation can be circumvented, as I explain in this blog post.

Resource-Based Constrained Delegation

RBCD is very similar to Constrained Delegation, except that the direction of the constraint is reversed. It specifies who is allowed to delegate to a service rather than who the service is allowed to delegate to. In other words, if Server A is allowed to delegate to Server B in Constrained Delegation, the constraint would be configured in an attribute of Server A. In RBCD, it would be configured in an attribute of Server B.

Another important difference between Constrained Delegation and RBCD is that Constrained Delegation specifies the SPN of the target service. In contrast, RBCD specifies the SID of the originating service in a Security Descriptor.

Required privileges

Configuring Unconstrained Delegation and Constrained Delegation requires the SeEnableDelegation privilege, which, by default, is granted only to Domain Admins. Therefore, even if a user had full control (GenericAll) on an AD account, he would not be able to configure either of these Kerberos delegation types without also having the SeEnableDelegation privilege. Unlike Unconstrained Delegation and Constrained Delegation, RBCD requires the right to change the msDS-AllowedToActOnBehalfOfOtherIdentity attribute but no special privileges.

Note that users need special privileges to change the Constrained Delegation configuration, but no special privileges are required for changing SPNs. Therefore, it may be interesting to tackle scenarios with the compromise of Constrained Delegation from a different angle—manipulating the SPN attribute rather than the delegation configuration.

Setting the stage

Suppose there are three servers in the environment: ServerA, ServerB, and ServerC. ServerA is configured with Constrained Delegation to a certain SPN. The attacker compromised ServerA and the account NotAdmin, which has WriteSPN rights on computer/service accounts in the environment. The attacker’s goal is to compromise ServerC.

 

Ghost SPN-jacking

The first scenario is the simplest one. ServerA is configured for Constrained Delegation to a SPN previously associated with a computer or service account that no longer exists. It could be a standard SPN, such as cifs/hostname, associated with a deleted computer/service account or a renamed computed account if the SPNs were updated accordingly. Or the account could be a custom SPN with a non-standard service class that was removed from the computer/service account, or the account itself could no longer exist.

In this scenario, the attacker can add the affected SPN to ServerC and then run the full S4U attack using ServerA’s account to obtain a service ticket for a privileged user to ServerC.

The service name of that ticket would not be valid for accessing ServerC because the hostname wouldn’t match, and the service class might be useless. However, the important thing is that the ticket is encrypted for ServiceC, and the service name is not in the encrypted part of the ticket, so the attacker can change it to a valid one.

Finally, the attacker can pass –the ticket and compromise ServerC.

The attack chain is illustrated in the following diagram:

The attack is demonstrated in the following screen capture:

Live SPN-jacking

The second scenario is a bit more contrived. ServerA is configured for Constrained Delegation to a SPN currently associated with ServerB, and the attacker has WriteSPN rights on ServerB and ServerC.

In fully patched environments, only Domain Admins would be permitted to configure conflicting SPNs, meaning SPNs associated with two or more different accounts. Therefore, if the attacker in this scenario tried to add the target SPN to ServerC, the DC would reject that change because it is already associated with ServerB.

The attacker can circumvent that barrier by temporarily removing the target SPN from ServerB and only then adding it to ServerC. The attacker can then run the full S4U attack using ServerA’s account to obtain a service ticket for a privileged user to ServerC.

As in the previous scenario, the service name of that ticket would not be valid for accessing ServerC. However, the important thing is that the ticket is encrypted for ServerC, and the service name is not in the encrypted part of the ticket, so the attacker can change it.

Finally, the attacker can pass –the ticket and compromise ServerC.

A well-behaved attacker should also roll back the changes by removing the target SPN from ServerC and restoring it to ServerB.

The attack chain is illustrated in the following diagram:

SPN-jacking with the HOST Service Class

It gets more interesting when the targeted SPN is not explicitly defined. By default, computer accounts have SPNs associated with the service classes TERMSRV, RestrictedKrbHost, and HOST. If other services are installed, such as LDAP or SQL Server, additional SPNs are added for those, too.

The HOST service class is mapped to the following service classes by default:
alerter, appmgmt, cisvc, clipsrv, browser, dhcp, dnscache, replicator, eventlog, eventsystem, policyagent, oakley, dmserver, dns, mcsvc, fax, msiserver, ias, messenger, netlogon, netman, netdde, netddedsm, nmagent, plugplay, protectedstorage, rasman, rpclocator, rpc, rpcss, remoteaccess, rsvp, samss, scardsvr, scesrv, seclogon, scm, dcom, cifs, spooler, snmp, schedule, tapisrv, trksvr, trkwks, ups, time, wins, www, http, w3svc, iisadmin, msdtc.

If the attacker tried to target a service class mapped to HOST, the domain controller would reject adding that service class to ServerC, even though it is not directly associated with ServerB. The attacker would first have to remove the HOST SPNs from ServerB and then explicitly add the target SPN to ServerC. However, after adding the target SPN to ServerC, the attacker can add the HOST SPNs back to ServerB without encountering any validation errors, despite already having a mapped SPN associated with ServerC, as demonstrated in the following screenshot:

When requesting service tickets to the ambiguous SPN, cifs/SERVERB in the screenshot above, the Domain Controller issues it for ServerC rather than ServerB.

The attack chain is illustrated in the following diagram:

How can attackers use SPN-jacking?

If an attacker compromised an account with GenericAll or GenericWrite rights on computer accounts, the attacker could use RBCD or Shadow Credentials to compromise the associated host or service. I suspect compromising an account with only WriteSPN rights on computer accounts is not very likely. However, chained with the compromise of a host with Constrained Delegation already configured, attackers could use this technique in environments where RBCD and Shadow Credentials are monitored or blocked. Defenders should follow the recommendations below to mitigate SPN-jacking attacks.

Detecting SPN-jacking

Changes to the ServicePrincipalName attribute of a computer account generate security events with the ID 4742 (A computer account was changed) on the domain controller. The event details show the changed attributes and their new value. Defenders can detect SPNs with a hostname different than the computer’s DNS names, as shown in the screenshot below:

Removing the HOST service class from a computer account may also be suspicious.

The S4U attack generates two security events with ID 4769 (A Kerberos service ticket was requested).

The first event is for S4U2Self. Defenders can detect it when the account information and service information point at the same account, as shown in the screenshot below:

The second event is for S4U2Proxy. Defenders can detect it when the Transited Services attribute is not blank, as shown in the screenshot below:

Preventing SPN-jacking

Defenders can apply several tactics to prevent this type of abuse:

  • Regularly audit Active Directory for Constrained Delegation pointing to ghost SPNs
  • Regularly audit Active Directory for anomalous WriteSPN rights
  • Add all privileged accounts to the Protected Users group to block any attempts to impersonate them through Kerberos delegation

Attackers can manipulate the SPN of computer/service accounts to redirect preconfigured Constrained Delegation to unintended targets, even without obtaining SeEnableDelegation privileges.

While the scenarios described in this article are not common, they can present viable attack paths when a compromised account is configured for Constrained Delegation that would otherwise be considered benign or as an alternative to RBCD and Shadow Credentials.

Defenders should take the necessary steps to detect and prevent such attacks.

References

This post was also published at shenaniganslabs.io and eladshamir.com.

About the author
Elad Shamir
Elad Shamir Semperis Director of Breach Preparedness and Response
Elad Shamir, Semperis Director of Breach Preparedness and Response, is a seasoned information security professional with extensive experience in planning and executing red team operations and other offensive security services. Linkedin
Unlock cyber resilience. Get a demo