# BadSuccessor: How the Feature That Killed Service-Account Attacks Became Domain Admin

> Windows Server 2025 delegated MSAs were built to end kerberoasting. For one summer, a single OU permission turned dMSA succession into Domain Admin rights.

*Published: 2026-07-19*
*Canonical: https://paragmali.com/blog/badsuccessor-how-the-feature-that-killed-service-account-att*
*© Parag Mali. All rights reserved.*

---
<TLDR>
Windows Server 2025's delegated Managed Service Account (dMSA) was built to end the service-account credential-theft era: its secret never leaves the domain controller, and a one-click supervised migration lets it *supersede* a legacy account and inherit that account's access. In May 2025, Akamai's Yuval Gordon showed that the Kerberos KDC honors that migration's succession link (`msDS-ManagedAccountPrecededByLink`) without ever checking that the superseded account consented. So a low-privileged user who can create a dMSA in a single organizational unit can name any account, up to Domain Admins, as its predecessor and inherit that account's full security context and Kerberos keys, without ever touching the target. The exposure was real but conditional (at least one Windows Server 2025 domain controller plus a generated KDS root key, roughly 0.7% of Active Directory domains at disclosure) and brief (patched as CVE-2025-53779 in August 2025). This is the story of how the feature built to end service-account attacks briefly became the cleanest domain takeover in years.
</TLDR>

## 1. One ACE, No Password Reset, Domain Admin

UserA is nobody. She sits in no privileged group, owns no server, and holds exactly one delegated permission: the right to create child objects in a single, forgotten organizational unit that some administrator carved out years ago and never revisited. Twelve minutes later she is authenticating to every machine in the forest as the built-in Administrator, and she never touched the Administrator account, never reset a password, never added herself to a group, never dumped LSASS, and never extracted the krbtgt key.

Here is the whole path, at altitude. UserA creates one object in that OU, a new account type called a delegated Managed Service Account. She writes two attributes on it: a link that names the Administrator as the account this new object *succeeds*, and a small integer that declares the succession already finished.

Then she points a machine she controls at a domain controller and asks for a Kerberos ticket for her new account. The domain controller reads the succession link, believes it, and stamps the Administrator's identity into her ticket. That is the attack. Akamai, who disclosed it, describes the result exactly: the operator can "act with the privileges of any user in Active Directory, without modifying the target object" [@akamai-readme].

Sit with the negative space, because it is the entire point. No Domain Admin password changed. No membership was added to any privileged group. No access-control entry on the Administrator object ever fired, because the Administrator object was never opened, read, or written [@akamai-readme]. Nothing was cracked offline. No replication right was invoked. Every classic Active Directory takeover leaves one of those marks; this one leaves none of them, because the target is a bystander to its own impersonation [@specterops-badsuccessor].

> **Key idea:** The account type Microsoft engineered to end service-account attacks -- to make stolen and cracked service credentials a thing of the past -- briefly became the cleanest domain takeover in years. That is not a contradiction to explain away. It is the thing this article explains: a single feature can be a genuine security improvement *and* an escalation primitive at the same time, and the reason is precise.

Two facts keep that framing honest, and I will hold them in view for the whole article rather than spring them at the end. First, this was never a universal exposure. It requires a domain running at least one Windows Server 2025 domain controller with a generated KDS root key, and at disclosure Tenable's Satnam Narang estimated that only about 0.7% of Active Directory domains met that bar [@helpnet-patch] [@specterops-badsuccessor].

Second, the window was short. Yuval Gordon of Akamai disclosed the technique, named BadSuccessor, on May 21, 2025 [@jimsycurity-dmsas], and Microsoft closed the direct escalation with CVE-2025-53779 in the August 2025 update [@nvd-cve] [@helpnet-patch].

> **Note:** Every claim in this article about "one OU permission to Domain Admin" lives inside a gate: a Windows Server 2025 domain controller plus a generated KDS root key, roughly 0.7% of domains at disclosure, and a remediation window that ran from May to August 2025 [@helpnet-patch] [@nvd-cve]. The mechanism is severe; the population was narrow. Both are true.

To see how a safety feature became the cleanest takeover in years, we have to start where its designers started: with the problem it was built to solve.

## 2. The Service-Account Problem

Ask a question that only sounds simple: how does a background service prove who it is? A human logs in and types a password. A batch job, a database engine, or a web application has no one at the keyboard, yet it still needs a domain identity so it can request tickets, read shares, and talk to other servers under least privilege.

For roughly two decades the standard answer in Active Directory was the same: give the service an ordinary user account, register a Service Principal Name on it so clients can ask Kerberos for tickets to it, and set a password by hand.

<Definition term="Service Principal Name (SPN)">
A unique name that ties a running service (for example `MSSQLSvc/db01.corp.local:1433`) to the account that hosts it. When a client wants to reach that service over Kerberos, it asks the domain controller for a ticket to the SPN, and the domain controller encrypts part of that ticket under the long-term key of whatever account owns the SPN [@mitre-t1558-003].
</Definition>

That one sentence -- "set a password by hand" -- is the whole weakness, and it took years to see how deep it ran. The account's long-term Kerberos key is derived directly from its password. And here is the property nobody designed on purpose: *any* authenticated user in the domain can request a service ticket for *any* SPN.

<Definition term="Key Distribution Center (KDC)">
The Kerberos authentication service that runs on every Active Directory domain controller. It issues the ticket-granting tickets and service tickets that prove identity across the domain, and it signs the authorization data inside them. When we say later that "the KDC decides who you are," this is the component we mean; our [Kerberos in Windows article](/blog/kerberos-in-windows-the-other-half-of-ntlmless/) walks the full exchange.
</Definition>

Put those two facts together and a quiet catastrophe falls out. An attacker asks the KDC for a service ticket to some `svc_sql` account, receives a blob encrypted under that account's password-derived key, and walks away to crack it offline, on their own hardware, at their own pace, with zero packets ever sent to the SQL host. A service password of `Summer2024!` falls in seconds. This is Kerberoasting, and it is the design pressure behind everything that follows.

<Definition term="Kerberoasting">
An offline credential attack, introduced by Tim Medin at DerbyCon 2014, in which any domain user requests service tickets for target SPNs and cracks the tickets' encryption offline to recover the service accounts' passwords, without ever authenticating to the services themselves [@irongeek-derbycon] [@mitre-t1558-003].
</Definition>

Medin's own framing of the talk names the danger with unusual economy: it is "a way to attack the credentials of a remote service without sending traffic to the service as well as rewriting tickets to access systems" [@irongeek-derbycon]. The full attack surface of legacy service accounts -- shared secrets, stale passwords, over-broad rights -- extends well beyond this post; here only one property matters.

<PullQuote>
Any authenticated user can request a service ticket for any SPN, and that ticket is encrypted under a key derived from a human-chosen password. The password is therefore crackable offline, by anyone, with no traffic to the service.
</PullQuote>

That is the shift the rest of this story depends on. A service account is not "just an account with a password you keep secret." Its secret is broadcast, on request, to every member of the domain, in a form built to be attacked at leisure.

The only durable fix is to make the secret itself uncrackable: machine-generated, long, and rotated automatically, so that "request a ticket, crack the key" stops paying. Microsoft would eventually say exactly this in its own guidance, recommending managed service accounts precisely because "AD machine account credentials are long and randomly generated" and so make brute force impractical [@ms-kerberoasting-guidance].

<Aside label="A dead end worth remembering: GPP cPassword">
Before the managed-account lineage matured, administrators tried to industrialize the old model instead of replacing it. Group Policy Preferences let them push service and local-account passwords across the domain -- but stored them reversibly encrypted under a *published* AES key in SYSVOL, readable by every authenticated user. Microsoft killed the feature with MS14-025 on May 13, 2014 [@ms14-025]. The lesson the lineage absorbed was blunt: a centrally distributed secret is a centrally stealable secret. The next generations would refuse to distribute the secret at all.
</Aside>

Microsoft's first attempt to take the human out of the password lifecycle shipped in 2009, and it immediately hit a wall.

## 3. Two Generations of Managed Accounts: sMSA and gMSA

If the fix is "let the machine own the secret," why did it take three tries and sixteen years? Because each generation solved the previous one's failure and quietly exposed a new one. The lineage is not a story of incompetence; it is a story of residuals, where every honest improvement leaves exactly one thing still wrong, and the next generation is built to answer that one thing.

<Mermaid caption="The sixteen-year managed-account lineage, and the single inflection that turned it into an attack">
flowchart LR
    A["Legacy service account, static password"] --> B["sMSA 2009, single-host managed password"]
    B --> C["gMSA 2012, multi-host via KDS root key"]
    C --> D["dMSA 2024, machine-bound secret, one-click migration"]
    D --> E["BadSuccessor May 2025, succession link abused"]
    E --> F["CVE-2025-53779 Aug 2025, KDC validates the link"]
    K["Kerberoasting 2014, offline key cracking"] -.-> D
</Mermaid>

**Generation one: the standalone MSA (sMSA), 2009.** Shipped with Windows Server 2008 R2, the standalone Managed Service Account removed the human from the password lifecycle entirely [@gmsa-overview]. The operating system generates the account's password, rotates it automatically, and manages the SPN, so there is no admin-chosen secret left to crack. Microsoft's own summary is that these accounts "eliminate the need for an administrator to manually administer" the SPN and credentials [@understand-service-accounts]. It worked, and it defeated the specific thing Kerberoasting preyed on -- for services that live on a single machine.

That last clause is the residual. An sMSA is bound to one host, so it "can't be shared among multiple computers" and "can't be used in server clusters" [@understand-service-accounts]. The moment a service is load-balanced across a farm or clustered for availability -- which is most services worth protecting -- the sMSA model breaks, and teams fall back to an ordinary shared-password account. Kerberoasting comes right back in through that fallback.

<Sidenote>An sMSA password is long by design -- hundreds of characters -- and rotates on a default interval near 30 days, which is what makes it uncrackable in practice. The length, not any secrecy trick, is the defense [@understand-service-accounts] [@gmsa-getting-started].</Sidenote>

**Generation two: the group MSA (gMSA), 2012.** Windows Server 2012 generalized the managed secret to a group of hosts. A domain-wide key, the [KDS root key](/blog/dpapi-and-dpapi-ng-the-credential-vault-under-everything/), lets every authorized host derive the same managed password for the account, so a clustered or load-balanced service can finally run under one managed identity. Microsoft states it plainly: the gMSA "provides the same functionality within the domain and also extends that functionality over multiple servers," and the Microsoft Key Distribution Service (`kdssvc.dll`) "lets you securely obtain the latest key" for the account [@gmsa-overview].

<Definition term="Group Managed Service Account (gMSA)">
A managed service account, introduced in Windows Server 2012, whose password is not stored but *derived* on demand from a domain-wide KDS root key. Any host listed in the account's `msDS-GroupMSAMembership` attribute can compute the current password, which lets a whole server farm authenticate as one managed identity [@gmsa-overview].
</Definition>

<Definition term="KDS Root Key">
A secret held by domain controllers, created with `Add-KdsRootKey`, from which gMSA and dMSA managed passwords are derived. It is the shared root of the multi-host managed-password scheme -- and, because it must exist for a dMSA to function, its presence in a domain is also one of the two preconditions BadSuccessor requires [@gmsa-overview] [@specterops-badsuccessor].
</Definition>

The gMSA solved the farm problem, and it left its own residual, one Microsoft names without flinching in the dMSA documentation: although gMSAs use "machine generated and autorotated passwords, the passwords are still not machine bound and can be stolen" [@dmsa-overview]. The secret is machine-*retrievable*, not machine-*bound*. Any host authorized in `msDS-GroupMSAMembership`, or anyone who can read the password blob with sufficient rights, can compute the real password. On top of that, moving a running legacy service onto a gMSA is a manual, disruptive project that many teams simply never finish.

<Sidenote>Not every service identity is a supersession in this lineage. Virtual accounts (`NT SERVICE\*`) and Windows LAPS solve adjacent problems -- per-service local identities and local-administrator password rotation, respectively -- and run alongside the MSA family rather than replacing it [@understand-service-accounts] [@laps-overview].</Sidenote>

The table makes the residual chain explicit.

| Generation | Year | Secret rotation and location | Machine-bound? | Residual that drove the next generation |
|---|---|---|---|---|
| Legacy service account | pre-2009 | Human-set password, becomes the account's key | No | Kerberoastable; static and rarely rotated |
| sMSA (standalone) | 2009 | Auto-rotated, OS-managed password | Bound to one host | Cannot span clusters or load-balanced farms |
| gMSA (group) | 2012 | Derived from the KDS root key, retrievable by authorized hosts | No -- retrievable | Password still stealable; migration is manual |
| dMSA (delegated) | 2024 | Randomized secret held only on the domain controller | Yes | Succession link honored without consent -- BadSuccessor |
| dMSA, patched | 2025 | Same, plus KDC link validation at ticket time | Yes | Over-broad OU rights (ACL hygiene) remain |

Two demands were left for generation three: make the secret genuinely un-retrievable, so it never leaves the domain controller, and make migration one-click, so the manual project that stalled everyone finally becomes trivial. The first demand is the one everybody wanted. The second is the one that introduced the machinery BadSuccessor would break.

## 4. dMSA and the Supervised Migration

The delegated Managed Service Account is generation three, and it arrived with Windows Server 2025, which reached general availability on November 1, 2024 [@ws2025-release-info] [@neowin-ga]. It answers both leftover demands: it makes the secret genuinely un-retrievable, and it makes migration one-click. To deliver that one-click migration, it teaches the KDC to honor a succession link -- and that single design choice is the entire story of this article.

Start with what dMSA got right, because it is a real advance. A dMSA's authentication is bound to a machine identity mapped in Active Directory, so only specified machines can use it. Its secret is a randomized value "derived from the machine account credential" and held by the domain controller, and Microsoft is explicit that it "can't be retrieved or found anywhere other than on the DC" [@dmsa-overview]. Where a gMSA password could be computed by any authorized host, a dMSA secret never leaves the domain controller at all, and it can be further sealed by Credential Guard.

<Definition term="Delegated Managed Service Account (dMSA)">
The third-generation Windows managed service account, introduced in Windows Server 2025. Its secret is randomized, machine-bound, and held only by the domain controller, which is what finally defeats offline credential theft against service accounts. It also ships a supervised in-place migration that lets a dMSA *supersede* a legacy service account and inherit its access [@dmsa-overview].
</Definition>

<Sidenote>Credential Guard can seal the dMSA secret inside the isolated LSA, so even a fully compromised host cannot read it. This hardening is real, but it is not load-bearing for the attack that follows -- BadSuccessor never needs the secret.</Sidenote>

Now the load-bearing novelty: the *supervised in-place migration*. Instead of the manual, disruptive gMSA cutover that teams abandoned, a dMSA can **supersede** a legacy account. Password authentication to the old account is blocked, and authentication is redirected through the Local Security Authority to the dMSA, which, in Microsoft's own words, "has access to everything the previous account could access in AD" [@dmsa-overview].

<PullQuote>
During the supervised migration, the dMSA takes over the resources the legacy account was using, and the two can co-exist for a time until that account is disabled. The successor "has access to everything the previous account could access in AD." -- Microsoft, Delegated Managed Service Accounts overview [@dmsa-overview]
</PullQuote>

How does the successor inherit that access? Through the directory, driven by two PowerShell cmdlets that write a small set of attributes. `Start-ADServiceAccountMigration` opens the migration: it sets the dMSA's `msDS-DelegatedMSAState` to 1, points `msDS-ManagedAccountPrecededByLink` at the legacy account, sets `msDS-SupersededAccountState` to 1 and `msDS-SupersededManagedServiceAccountLink` back at the dMSA, and grants the legacy account Generic Read on all of the dMSA's properties plus Write on `msDS-GroupMSAMembership`, so it can participate.

`Complete-ADServiceAccountMigration` closes it: it sets `msDS-DelegatedMSAState` to 2, copies the SPNs, the `msDS-AllowedToDelegateTo` delegation settings, and the authentication policy onto the dMSA, sets `msDS-SupersededServiceAccountState` to 2, and disables the old account [@dmsa-overview].

<Mermaid caption="The dMSA supervised migration state machine: what Start- and Complete-ADServiceAccountMigration write, and where the KDC later trusts the link">
flowchart TD
    S0["Legacy service account, still active"] --> S1["Start-ADServiceAccountMigration"]
    S1 --> A1["dMSA msDS-DelegatedMSAState set to 1, begun"]
    S1 --> A2["dMSA msDS-ManagedAccountPrecededByLink points at legacy account"]
    S1 --> A3["Legacy account granted Generic Read on all dMSA properties, plus Write on msDS-GroupMSAMembership"]
    A1 --> C1["Complete-ADServiceAccountMigration"]
    A2 --> C1
    A3 --> C1
    C1 --> B1["dMSA msDS-DelegatedMSAState set to 2, completed"]
    C1 --> B2["SPNs, delegation, and auth policy copied to dMSA"]
    C1 --> B3["Legacy account disabled"]
    B1 --> KDC["At login, KDC honors the link and copies the predecessor security context into the dMSA PAC"]
</Mermaid>

The attribute types matter, so hold two of them apart. `msDS-ManagedAccountPrecededByLink` is a distinguished-name *link*, a back-reference that names the predecessor. `msDS-DelegatedMSAState` is a *state integer*: 1 means the migration has begun, 2 means it has completed [@dmsa-overview]. When the dMSA later authenticates, the KDC reads that link and duplicates the named predecessor's security context onto the successor's Privilege Attribute Certificate.

<Definition term="msDS-ManagedAccountPrecededByLink">
The directory attribute on a dMSA that names, by distinguished name, the account this dMSA supersedes. During Kerberos authentication the KDC treats this link as authority to copy the named account's SIDs and keys into the dMSA's ticket. It is a back-reference, not a permission grant -- and, as the next section shows, the KDC never checks that the named account agreed to be named [@dmsa-overview] [@specterops-badsuccessor].
</Definition>

<Definition term="Privilege Attribute Certificate (PAC)" sameAs="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/c38cc307-f3e6-4ed4-8c81-dc550d96223c">
The authorization payload the KDC builds and signs inside every Kerberos ticket. It carries the account's SIDs and group memberships -- the data a target server reads to decide what the ticket-holder may do. Copying a predecessor's security context "onto the PAC" means writing the predecessor's SIDs into the successor's signed authorization data [@ms-pac].
</Definition>

| Attribute | Written by | Value | Type |
|---|---|---|---|
| `msDS-DelegatedMSAState` | Start-, then Complete- | 1 (begun), then 2 (completed) | State integer |
| `msDS-ManagedAccountPrecededByLink` | Start- | DN of the superseded account | DN link |
| `msDS-SupersededAccountState` | Start- | 1 | State integer |
| `msDS-SupersededManagedServiceAccountLink` | Start- | DN of the dMSA | DN link |
| `msDS-GroupMSAMembership` | Start- (legacy account granted Write here; Generic Read on all properties) | principals allowed to use the secret | Security descriptor |
| `msDS-SupersededServiceAccountState` | Complete- | 2 | State integer |

The safety premise is hiding in the word *supervised*. In the legitimate flow, the real superseded account participates: it is granted read on the dMSA and it refreshes its own ticket-granting ticket as part of the handover. Microsoft even fences the feature to keep it coherent, noting that "you can't migrate from a managed service account or a gMSA to a dMSA" [@dmsa-overview]. The migration is designed to be safe *because* the predecessor is in the loop.

The following model reads a succession record the way the KDC does. Notice how little it takes to look "completed."

<RunnableCode lang="js" title="How the KDC reads a dMSA succession record">{`
// msDS-DelegatedMSAState: 0 = none, 1 = migration begun, 2 = migration completed
const stateNames = { 0: 'none', 1: 'begun', 2: 'completed' };

function readSuccession(record) {
  const state = stateNames[record.delegatedMSAState] || 'unknown';
  const linked = record.precededByLink || '(none)';
  console.log('dMSA:        ' + record.name);
  console.log('State:       ' + record.delegatedMSAState + ' (' + state + ')');
  console.log('Preceded by: ' + linked);
  // The only two things the pre-patch KDC needs to inherit a context:
  const willInherit = record.delegatedMSAState === 2 && Boolean(record.precededByLink);
  console.log('KDC inherits predecessor SIDs and keys? ' + (willInherit ? 'YES' : 'no'));
}

// A legitimately completed migration record:
readSuccession({
  name: 'svc-web-dmsa',
  delegatedMSAState: 2,
  precededByLink: 'CN=svc-web,OU=Service Accounts,DC=corp,DC=local'
});
`}</RunnableCode>

The migration is safe because the superseded account participates. But look again at what the KDC actually reads: a state integer and a link. What happens if nobody ever checks that the predecessor participated at all?

## 5. BadSuccessor: The KDC Trusts the Link

In May 2025, Yuval Gordon of Akamai asked the question the migration's designers apparently never wrote down: before the KDC duplicates a predecessor's security context onto a successor, what does it actually verify? Not that an administrator approved the migration. Not that the predecessor participated. Not even that the predecessor is aware it has a successor. The answer is nothing. The KDC reads the link and believes it.

<PullQuote>
The KDC "blindly trusts any value set in the `msDS-ManagedAccountPrecededByLink` attribute of the dMSA ... to duplicate the preceded account's security context on the dMSA's ... PAC." -- Jim Sykora, SpecterOps [@specterops-badsuccessor]
</PullQuote>

That is the whole vulnerability, and everything else is consequence. The legitimate migration writes a link and a state integer; so can anyone who can create a dMSA. The attacker forges a *completed* migration that never happened. Three writes do it, and all three land on the attacker's own new object [@specterops-badsuccessor]:

1. Set `msDS-ManagedAccountPrecededByLink` to the distinguished name of any chosen victim -- a Domain Admin, for instance.
2. Set `msDS-DelegatedMSAState` to 2, declaring the migration already complete.
3. Add a principal the attacker controls to `msDS-GroupMSAMembership`, which "can be any security principal(s), including a group" and is "abusable directly to a user account," so the attacker can actually request the dMSA's tickets [@specterops-badsuccessor].

<RunnableCode lang="js" title="Forging a completed migration: three writes, none on the victim">{`
// BadSuccessor forges a COMPLETED migration the KDC will trust.
// It is three attribute writes on an attacker-created dMSA -- and zero writes to the victim.
function forgeSuccession(victimDN, attackerPrincipal) {
  const dmsa = { name: 'attacker-dmsa', delegatedMSAState: 0, precededByLink: null, groupMSAMembership: [] };

  dmsa.precededByLink = victimDN;             // Write 1: name any victim as predecessor
  dmsa.delegatedMSAState = 2;                  // Write 2: declare migration complete
  dmsa.groupMSAMembership.push(attackerPrincipal); // Write 3: authorize attacker to use it

  const victimTouched = false;                 // the victim object is never opened
  console.log('Forged record: ' + JSON.stringify(dmsa));
  console.log('Victim object modified? ' + victimTouched);
  const willStamp = dmsa.delegatedMSAState === 2 && Boolean(dmsa.precededByLink);
  console.log('KDC stamps victim SIDs into the PAC? ' + willStamp);
}

forgeSuccession('CN=Administrator,CN=Users,DC=corp,DC=local', 'UserA');
`}</RunnableCode>

From a host running Windows Server 2025 or Windows 11 24H2, the attacker then simply asks for the dMSA's ticket-granting ticket. The KDC honors the link and issues it.

<Mermaid caption="BadSuccessor impersonation: three writes and two Kerberos messages turn one OU permission into Domain Admin">
sequenceDiagram
    participant UserA as UserA, one OU permission
    participant DIR as Active Directory
    participant KDC as KDC on a Server 2025 DC
    participant Res as Any domain resource
    UserA->>DIR: Create a dMSA in the OU UserA controls
    UserA->>DIR: Write ManagedAccountPrecededByLink to a Domain Admin
    UserA->>DIR: Write DelegatedMSAState to 2 and add self to GroupMSAMembership
    UserA->>KDC: Request a TGT for the new dMSA
    KDC->>DIR: Read the succession link, run no consent check
    KDC-->>UserA: TGT whose PAC carries the Domain Admin SIDs
    UserA->>Res: Authenticate as the Domain Admin
    Res-->>UserA: Access granted, target object never touched
</Mermaid>

> **Note:** There is no separate bug here to patch away cleanly. The property that makes supervised migration seamless -- the KDC accepting the succession link as authority to inherit a context -- is exactly the property BadSuccessor turns into escalation. The feature and the primitive are the same mechanism read two ways [@specterops-badsuccessor].

### Two primitives, not one

The research names two distinct payoffs from the same staging, and they matter separately.

**Impersonation.** The KDC stamps the victim's SIDs -- including Domain Admins, if that is who you named -- into the successor's PAC, and the attacker authenticates anywhere as the victim. Akamai's summary is exact: the operator can "act with the privileges of any user in Active Directory, without modifying the target object" [@akamai-readme]. No group changed, no password reset, no access-control entry on the victim ever evaluated, because the victim was never opened. The PAC's group-SID fields carry the impersonation; our [KRBTGT article](/blog/krbtgt-the-account-that-owns-active-directory/) explains why "the KDC decides who you are" is the crux of domain trust.

**Credential theft.** This is the quieter, arguably worse primitive. Akamai found that the succession link "doesn't just link the dMSA to the superseded account for permission purposes, it also lets the dMSA inherit its keys," and that "the KDC includes the previous account's keys in the new dMSA's key package structure" [@akamai-disclosure]. Because the attacker chose the predecessor, the response hands over the victim's *actual* Kerberos keys.

That is not a one-shot impersonation. It is durable credential material that survives the dMSA's deletion and opens a path to full forest compromise -- the same end state as DCSync, without the replication rights our [DCSync and DCShadow article](/blog/two-checkmarks-and-the-keys-to-the-kingdom-how-active-direct/) requires.

<Sidenote>The key package carries the predecessor's current keys -- observed as RC4-HMAC, AES256, and AES128 (encryption types 23, 18, and 17 in the IANA registry) -- plus a single previous RC4-HMAC key [@akamai-disclosure] [@iana-kerberos]. Microsoft does not document this package publicly, so treat the behavior as reconstructed from the disclosure rather than from a specification.</Sidenote>

The difference between the legitimate operation and the attack is a single fact: whether the predecessor was ever in the room.

<Mermaid caption="Legitimate migration versus BadSuccessor: the only difference is whether the predecessor ever participates">
flowchart TD
    subgraph LEGIT["Legitimate migration"]
        L1["Admin runs Start- and Complete-ADServiceAccountMigration"] --> L2["Predecessor granted read on the dMSA, refreshes its own TGT"]
        L2 --> L3["Predecessor participates, consent is real in practice"]
        L3 --> L4["KDC copies the context to a genuine successor"]
    end
    subgraph ABUSE["BadSuccessor"]
        X1["Attacker creates a dMSA, writes the link plus state 2"] --> X2["Predecessor is never contacted"]
        X2 --> X3["No participation, no consent, target untouched"]
        X3 --> X4["KDC copies the context anyway"]
    end
</Mermaid>

### Exactly what it takes

Precision here is what keeps the argument honest. BadSuccessor is gated, not universal. The environmental gate is two things together: at least one Windows Server 2025 domain controller, and a generated KDS root key in the domain -- the same root key a dMSA needs to function [@specterops-badsuccessor] [@helpnet-patch].

The permission is CreateChild for the `msDS-DelegatedManagedServiceAccount` class on an organizational unit or a container -- or any right that yields it: GenericAll, WriteDACL, WriteOwner, or object ownership on the parent [@specterops-badsuccessor] [@forestall]. The attacker also needs a principal they control placed in the dMSA's `msDS-GroupMSAMembership`, and a Windows Server 2025 or Windows 11 24H2 host from which to request the dMSA's ticket [@sharpsuccessor] [@helpnet-disclosure].

> **Key idea:** The safety mechanism *is* the primitive. The KDC never verifies consent; it trusts `msDS-ManagedAccountPrecededByLink` on its face. So writing one link and one state integer on a dMSA I created makes the KDC impersonate anyone I name, up to Domain Admins, and hand me their keys -- while the target object is never opened, read, or written [@specterops-badsuccessor] [@akamai-readme].

One ACE. No target modification. Deterministic, not probabilistic. And it yields both impersonation and durable key theft from the same three writes. The obvious next question is the one every defender asked in the summer of 2025: in the real world, how bad is this?

## 6. Exploitation, Tooling, and the 91%

A primitive is only as dangerous as it is easy. What made BadSuccessor land so hard was not the mechanism alone but the measurement Akamai published alongside it: most examined environments were already stageable by ordinary users. Akamai's audit script, `Get-BadSuccessorOUPermissions.ps1`, reports which identities can create dMSAs and where, and its headline finding is blunt -- the technique "works in the default configuration," and "In 91% of the environments we examined, non-admin users had the required permissions" [@akamai-readme].

<PullQuote>
"In 91% of the environments we examined, non-admin users had the required permissions" to stage BadSuccessor. -- Akamai [@akamai-readme]
</PullQuote>

Why is that number so high? Because the permission is not the rare-sounding "CreateChild for the dMSA class." It collapses, through the ordinary Windows security model, to "any OU you already control at all."

<Mermaid caption="Why CreateChild collapses to any OU you control: the owner-to-GenericAll chain">
flowchart LR
    A["Attacker can create a dMSA in an OU"] --> B["Creator becomes the object Owner"]
    B --> C["Owner has implicit WriteDACL, checked before any Deny ACE"]
    C --> D["Owner grants self GenericAll on the dMSA"]
    D --> E["GenericAll yields WriteProperty on the succession attributes"]
    E --> F["Forge the completed migration"]
</Mermaid>

SpecterOps walks the chain: the principal that creates an object is highly likely to be set as its Owner, and an Owner holds an implicit WriteDACL that the access check evaluates *before* any Deny access-control entry [@specterops-badsuccessor]. So an attacker who can create a dMSA becomes its Owner, uses that implicit WriteDACL to grant themselves GenericAll, and thereby has WriteProperty on the succession attributes.

Equivalently, GenericAll, WriteDACL, WriteOwner, or ownership on the parent OU each collapse to "can create and weaponize a dMSA here." That is why an obscure-sounding right turns out to be held by non-admins in nine out of ten domains.

The following model is the logic of the audit script: given the environment and a list of OU access-control entries, who can stage the attack?

<RunnableCode lang="js" title="BadSuccessor exposure check (logic of Get-BadSuccessorOUPermissions.ps1)">{`
// Given the environment and OU access-control entries, can a non-admin stage BadSuccessor?
const enablingRights = ['CreateChild', 'GenericAll', 'WriteDacl', 'WriteOwner', 'Owns'];

function canStageBadSuccessor(env, ouAces) {
  if (!env.hasServer2025DC || !env.hasKdsRootKey) {
    return 'Not exposed: gate not met (needs a Server 2025 DC and a KDS root key).';
  }
  const risky = ouAces.filter(function (ace) {
    return !ace.isPrivilegedGroup && enablingRights.includes(ace.right);
  });
  if (risky.length === 0) return 'No non-admin principal can create-and-weaponize a dMSA here.';
  const who = risky.map(function (a) { return a.principal + ' (' + a.right + ')'; }).join(', ');
  return 'EXPOSED via: ' + who;
}

const env = { hasServer2025DC: true, hasKdsRootKey: true };
const ouAces = [
  { principal: 'HelpDesk', right: 'GenericAll', isPrivilegedGroup: false },
  { principal: 'UserA', right: 'CreateChild', isPrivilegedGroup: false },
  { principal: 'Domain Admins', right: 'GenericAll', isPrivilegedGroup: true }
];
console.log(canStageBadSuccessor(env, ouAces));
`}</RunnableCode>

> **Note:** Run Akamai's `Get-BadSuccessorOUPermissions.ps1` first. It needs only domain-read rights and gives you a same-day map of who can create dMSAs and where -- which is the exact list of OUs to treat as sensitive, whether or not your domain controllers are patched yet [@akamai-readme].

<Sidenote>That inventory is a floor, not a ceiling. The script "requires only domain read permissions," excludes built-in privileged groups like Domain Admins and Enterprise Admins, and "does not calculate effective permissions or expand group memberships," so its output deliberately under-reports rather than over-reports [@akamai-readme].</Sidenote>

On the offensive side, the tooling that emerged made the work factor a single command. **SharpSuccessor**, a .NET proof of concept by Logan Goins, "fully weaponiz[es]" the attack: one invocation stages the dMSA and its three attributes, after which the operator uses **Rubeus**<MarginNote>Rubeus is GhostPack's widely used C# toolkit for Kerberos ticket abuse.</MarginNote>, which added a `/dmsa` code path, to request and pass the successor's ticket [@sharpsuccessor]. There is no cracking step, no race, and no waiting.

Where kerberoasting's expected work grows with password entropy -- on the order of $O(2^{b})$ for a $b$-bit key -- BadSuccessor's cost is a constant $O(1)$: one object creation and three writes, whatever the victim's privilege.

Defenders got a graph model in the same window. SpecterOps and Jim Sykora expressed "who can BadSuccessor whom" as BloodHound edges -- `SupersededBy`, `ImpersonateSupersededAccount`, and `CompromiseSupersededAccountPreviousKeys` -- so the exposure becomes a single query over principals that can control an OU without being Tier Zero [@jimsycurity-dmsas]. Our [BloodHound article](/blog/ad-is-a-graph-how-bloodhound-made-defenders-think-like-attac/) explains why turning attack paths into graph edges changes what defenders can see.

<Definition term="Tier Zero">
The set of assets that can directly control the security of the entire domain or forest -- domain controllers, the accounts that administer them, and anything with a path to that control. The governing rule is that only Tier Zero may control Tier Zero. dMSA-creation rights belong in this set, even though nobody classified them that way before 2025.
</Definition>

<Definition term="Clean Source Principle">
SpecterOps' formulation of a long-standing security axiom: any subject that controls an object must be at least as trusted as that object. A non-Tier-Zero principal that can produce a Tier-Zero outcome violates it. BadSuccessor is a textbook violation -- a helpdesk-grade OU right yielding Domain Admin [@specterops-clean-source].
</Definition>

This is why BadSuccessor is not filed as "just another ACL abuse." It violates the Clean Source Principle by letting a non-Tier-Zero principal control a Tier-Zero outcome [@specterops-clean-source]; it requires no modification of the target; and it delivers both impersonation and key theft from one primitive. Inside its 0.7%-of-domains gate and its 91%-of-those-domains prevalence, calling it the cleanest domain takeover in years is a judgment, not a measurement -- but it is a defensible one [@helpnet-patch] [@akamai-readme].

If it is this clean and this available, the fair question is how it compares to the other one-step-to-Domain-Admin primitives the reader already fears.

## 7. BadSuccessor Among the Escalation Primitives

Every Active Directory attacker keeps a mental table titled "one step to Domain Admin." The value of placing BadSuccessor precisely is that it explains the feeling practitioners reported in May 2025 -- that this one felt different -- in terms of properties rather than adjectives.

Line up the usual entries. **Kerberoasting** recovers a service account's password, but it is offline and probabilistic: it needs a weak human-chosen password and pays off only if cracking succeeds [@mitre-t1558-003]. **AD CS ESC1** and its siblings mint an authentication certificate for any identity, but they need a misconfigured certificate template to exist first, which our [Certified Pre-Owned article](/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/) catalogs in full [@mitre-t1649].

**DCSync** pulls any account's hashes, but it requires the two directory-replication rights that a principal near Domain Admin already holds [@mitre-t1003-006]. **Golden Ticket** forges any ticket-granting ticket, but it presupposes you already have the krbtgt key -- that is, you have already won [@mitre-t1558-001].

The nearest relative is not on that list by name. It is Resource-Based Constrained Delegation abuse.

<Definition term="Resource-Based Constrained Delegation (RBCD)">
A Kerberos delegation model in which a resource lists which accounts may impersonate users to it, via the `msDS-AllowedToActOnBehalfOfOtherIdentity` attribute. If an attacker can write that attribute on a target and control a suitable computer account, the S4U extensions let them obtain a service ticket as an arbitrary user to that resource [@wagging-the-dog].
</Definition>

<Aside label="The closest ancestor: Wagging the Dog">
In January 2019, Elad Shamir's "Wagging the Dog" showed that "if an attacker can control a computer object in Active Directory, then it may be possible to abuse it to compromise the host," because S4U2Self "allows generating a valid TGS for arbitrary users" whose "resulting TGS has a PAC with a valid KDC signature" [@wagging-the-dog]. That is BadSuccessor's exact shape: write one attribute, let the KDC mint a ticket that impersonates a target. The differences are what make BadSuccessor cleaner. RBCD abuse *modifies the target* -- it writes a delegation attribute onto the victim resource -- and it typically needs a controllable computer object. BadSuccessor writes only its own new object and never touches the victim at all.
</Aside>

<Sidenote>RBCD's classic enabler is `ms-DS-MachineAccountQuota`, which defaults to 10, letting an ordinary user join up to ten computer accounts and so obtain the controllable computer object the attack wants [@wagging-the-dog]. BadSuccessor needs no such object -- a user principal placed in `msDS-GroupMSAMembership` is enough.</Sidenote>

The matrix isolates why BadSuccessor felt uniquely clean.

| Primitive | Precondition | Touches the target? | Deterministic? | Payoff | Primary signal |
|---|---|---|---|---|---|
| BadSuccessor | One OU right, plus a Server 2025 DC and a KDS root key | No | Yes | Impersonation and the victim's keys | An anomalous directory write, if a SACL exists |
| Kerberoasting | A weak service-account password exists | No | No -- offline crack | The recovered password or key | Service-ticket requests, crackable ticket type |
| AD CS ESC1 | A vulnerable certificate template exists | No | Yes | An auth certificate for any identity | Certificate enrollment and issuance logs |
| RBCD / S4U | Write a delegation attribute on the target, plus a controllable computer | Yes | Yes | Impersonation | The attribute write on the target |
| DCSync | Two replication rights (near-Domain-Admin already) | No | Yes | Any account's password hashes | Replication sourced from a non-DC |
| Golden Ticket | The krbtgt key (full compromise already) | No | Yes | Any forged ticket-granting ticket | Ticket anomalies over time |

Read the columns as a single argument. Every rival needs one of three things BadSuccessor did not: a pre-existing high-value secret you must already hold (Golden Ticket, DCSync), a misconfiguration or weakness *on the target or template* (Kerberoasting, ESC1, RBCD), or a probabilistic crack that might fail (Kerberoasting). BadSuccessor asked for a single access-control entry on a single OU, inside the 0.7% environmental gate, and it modified nothing on the target [@akamai-readme] [@specterops-badsuccessor]. It is also the only row that yields *both* impersonation and durable key recovery.

<Sidenote>The disclosure date is worth pinning: Gordon released the BadSuccessor writeup on May 21, 2025, with the first wave of secondary coverage on May 22 [@jimsycurity-dmsas] [@helpnet-disclosure].</Sidenote>

BadSuccessor's rivals are all either noisy or gated by a scarce prerequisite. BadSuccessor was neither. Which forces an uncomfortable question: if a low-privileged user can become Domain Admin this cleanly, why did none of the standard detections fire?

## 8. Why It Was Nearly Invisible

Surely, the objection goes, some EDR, SIEM, or Kerberos-ticket monitor flags a helpdesk account suddenly wielding Domain Admin. It does not, and the reason is a proof from first principles, not a gap someone forgot to close.

Start with the ticket, because that is where defenders instinctively look. The ticket-granting ticket the attacker receives is cryptographically genuine: signed by the KDC, carrying a valid PAC, issued for a dMSA that the directory itself says was superseded. An abusive succession and a legitimate one produce *identical* tickets, because they exercise the identical code path with the identical inputs. There is no field that differs, no flag that flips.

It follows that no ticket-inspection detector can classify the ticket as malicious -- not because the vendors were lazy, but because there is nothing in the ticket to classify. The logon it produces (Event 4624) and the service-ticket requests that follow (Event 4769) are, likewise, requests for a dMSA the KDC genuinely blessed [@event-4624] [@event-4769].

> **Key idea:** Watch the write, not the ticket. The malice lives entirely in the *directory change* that forged the succession, never in the *ticket* that change produces. Any detection strategy that inspects tickets is chasing a signal that, by construction, is not there [@specterops-badsuccessor].

If the ticket is a dead end, only two other places can carry signal.

<Mermaid caption="Why detection has a floor: the ticket is legitimate by construction, so only the write or the behavior carries signal">
flowchart TD
    S["A low-privileged user just became Domain Admin. Where is the signal?"] --> Q1
    S --> Q2
    S --> Q3
    Q1&#123;"Inspect the issued ticket?"&#125; -->|Legitimate by construction| D1["Dead end: KDC-signed, valid PAC, real dMSA"]
    Q2&#123;"Inspect the directory write?"&#125; -->|SACL present| D2["Events 5136 and 5137 can fire"]
    Q2 -->|No SACL, the default| D3["No event at all"]
    Q3&#123;"Inspect behavior over time?"&#125; -->|MDI enabled| D4["Suspicious DMSA related activity alert"]
</Mermaid>

The first is the anomalous directory write itself. With the Audit Directory Service Changes subcategory enabled, Active Directory can emit Event 5136 when an object is modified and Event 5137 when one is created -- exactly the writes to `msDS-ManagedAccountPrecededByLink`, `msDS-GroupMSAMembership`, and `msDS-DelegatedMSAState`, and the dMSA's creation. But the same Microsoft primary states the load-bearing caveat: "Audit events are generated only for objects with configured system access control lists (SACLs)" [@audit-ds-changes]. The signal exists only where someone deliberately placed an auditing SACL in advance, which is not the default, and the event volume on domain controllers is high [@audit-ds-changes].

<Definition term="System Access Control List (SACL)">
The part of an object's security descriptor that specifies which access attempts generate audit events. Unlike a DACL, which grants or denies access, a SACL only produces logging -- and only for the objects on which one has been explicitly configured. No SACL, no 5136 or 5137, no matter how the subcategory is set [@audit-ds-changes].
</Definition>

> **Note:** Turning on the Audit Directory Service Changes subcategory is necessary but not sufficient. If the succession attributes and the OUs that hold dMSAs do not carry auditing SACLs, the attack generates no 5136 or 5137 at all. The subcategory and the SACLs are two separate switches, and both must be on [@audit-ds-changes].

The second place is behavioral analytics. Microsoft Defender for Identity added an XDR alert named "Suspicious DMSA related activity detected" (detector `xdr_SuspiciousDmsaAction`, severity High, mapped to MITRE T1555) that flags anomalous dMSA activity after the fact [@mdi-xdr-alerts] [@mitre-t1555]. Community teardown also records Event 2946 as a corroborating signal in the right configuration [@8bitsecurity]. Our [Microsoft Defender for Identity article](/blog/microsoft-defender-for-identity-the-defensive-ad-stack-that-/) covers the detections added after disclosure.

| Signal | What it catches | On by default? | Limitation |
|---|---|---|---|
| Event 5136 | A succession attribute was modified | No -- needs a SACL | Silent on un-SACL'd objects; high volume on DCs |
| Event 5137 | The dMSA object was created | No -- needs a SACL | Reads as benign object creation |
| Event 2946 | dMSA-related activity in the right configuration | No | Corroborating and configuration-dependent |
| MDI `xdr_SuspiciousDmsaAction` | Behavioral dMSA abuse | Only where MDI is deployed | Post-hoc and behavioral |
| Event 4662 on the victim | Directory access to the target object | Not applicable | Never fires -- the target is never touched |

Notice the last row. The event most AD detections lean on, directory-service-access on the target object, cannot help, because the target object is never accessed [@specterops-badsuccessor]. The same design coherence that made the feature clean made the abuse quiet: a detection can flag the anomalous write, but it can never call the ticket malicious, because the ticket is legitimate.

Detection could not see it, and, as the next section shows, access-control fixes could not fully stop it either. Only Microsoft could close it at the KDC -- and for three months, Microsoft said it would not.

## 9. The Patch and What It Left Standing

The remediation arc is the argument for the thesis's most important word: *briefly*. It is a short story with a slow beginning.

When Akamai disclosed BadSuccessor in May 2025, Microsoft's Security Response Center rated it Medium, assigned no CVE, and declined to ship a scheduled fix, saying a fix "will be worked on over time" [@specterops-badsuccessor]. For roughly three months, the cleanest domain takeover in years had an official severity of Medium and no patch on the calendar.

That changed on August 12, 2025. Microsoft assigned **CVE-2025-53779**, described as a "relative path traversal in Windows Kerberos" (CWE-23) with a CVSS 3.1 base score of **7.2 (High)** and vector `AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H` [@nvd-cve]. The advisory confirmed that an attacker "who successfully exploited this vulnerability could gain domain administrator privileges" while rating exploitation "less likely" [@helpnet-patch] [@msrc-cve]. The fix shipped for Windows Server 2025 in build **26100.4946**, delivered by **KB5063878** [@nvd-cve] [@kb5063878].

<Sidenote>Cite the fixed build carefully. NVD's `affected` block lists the fix at build 26100.4946, matching MSRC and KB5063878, while an internal CPE-match node lists 26100.4851. The correct build to patch to and to cite is 26100.4946 [@nvd-cve] [@kb5063878].</Sidenote>

What did the patch actually change? Akamai's follow-up analysis is specific: "changes in `kdcsvc.dll` force the KDC to validate the relationship at ticket time," so that "a one-way link from dMSA to the target no longer works," and "succeeding now requires controlling the account's object itself -- not just the dMSA" [@akamai-patch].<MarginNote>`kdcsvc.dll` is the Key Distribution Center service that runs on every domain controller; patching it changes how the KDC itself evaluates a succession.</MarginNote> In other words, the KDC now demands a *mutual* succession relationship before it will inherit a context, which the attacker's forged one-way link cannot satisfy.

<Mermaid caption="What the August 2025 patch changed: the KDC now requires a mutual succession link at ticket time">
flowchart LR
    subgraph BEFORE["Before the patch"]
        A1["Attacker writes a one-way link from dMSA to victim"] --> A2["KDC honors it, inheritance granted"]
    end
    subgraph AFTER["After CVE-2025-53779"]
        B1["Attacker writes a one-way link from dMSA to victim"] --> B2["KDC checks for a mutual link at ticket time"]
        B2 --> B3["One-way link rejected, escalation blocked"]
    end
</Mermaid>

| Date | Actor | Action | Evidence |
|---|---|---|---|
| May 21, 2025 | Yuval Gordon, Akamai | Public disclosure of BadSuccessor | [@jimsycurity-dmsas] |
| May 2025 | Microsoft (MSRC) | Rated Medium, no CVE, no scheduled patch | [@specterops-badsuccessor] |
| May 2025 | Akamai | Notes "no patch is currently available" | [@akamai-readme] |
| Aug 12, 2025 | Microsoft | CVE-2025-53779, fix in KB5063878 / build 26100.4946 | [@nvd-cve] [@kb5063878] |
| After patch | Akamai | Residual analysis: "BadSuccessor Is Dead, Long Live BadSuccessor (?)" | [@akamai-patch] |

Now the honest part, because the patch is narrower than the headline suggests. The enforcement went into the KDC, not into directory-side protection of the attribute -- `msDS-ManagedAccountPrecededByLink` is still writable. Akamai's own residual analysis notes that dMSA-based credential-acquisition and lateral-movement scenarios persist under some post-patch conditions, that the "migration still works even if the target account remains enabled," and that the fix closes the instant one-way escalation without touching the root cause [@akamai-patch].

That root cause is the 91%: over-broad CreateChild, GenericAll, WriteDACL, and WriteOwner rights on OUs, entirely unchanged by a Kerberos patch. A schema-modification caveat remains as well, since altering the schema could expose the dMSA class under other parents.

> **Note:** CVSS `PR:H` ("high privileges required") and "exploitation less likely" read strangely for a one-OU-permission Domain Admin, until you notice they measure two different things. `PR:H` is a per-instance judgment in the CVSS base score: staging the attack requires delegated create or write rights on an OU, which CVSS reads as a meaningful privilege. "Exploitation less likely" is not a CVSS field at all; it is MSRC's separate Exploitability Index, reflecting the environmental preconditions and the small qualifying population. Neither measures how hard the exploit is *inside* a qualifying domain, where the bar is low [@helpnet-patch] [@specterops-badsuccessor].

<Aside label="The severity debate">
The three-month gap between a Medium/no-CVE posture and CVE-2025-53779 is the article's most contested beat. Researchers argued the impact -- unconstrained impersonation of any principal, plus key theft -- warranted urgency; Microsoft's initial rating leaned on the narrow qualifying population and the environmental preconditions [@specterops-badsuccessor] [@helpnet-patch]. Both readings are internally consistent, which is precisely why the CVSS numbers feel low to practitioners: a score built to summarize a population reads oddly when you are standing inside one of the exposed domains.
</Aside>

There was always a cleaner fix available, and it is worth naming because it defines what "fully closed" would mean. Consent-verified succession -- gating the inheritance behind a privilege or extended right, the way Active Directory already gates sensitive operations with `SeEnableDelegationPrivilege` and per-attribute add authorization -- would make the KDC demand proof of authorization rather than a bare link. The machinery exists: MS-ADTS already defines per-attribute authorization for LDAP Add operations [@ms-adts-ldap-add] [@specterops-badsuccessor]. But building it is Microsoft's call, not a defender's.

The window closed. The lesson -- that a feature can ship an escalation primitive alongside it -- did not. So what should a defender or an operator actually do with all this?

## 10. What a Defender and an Operator Actually Do

Strip the drama and BadSuccessor becomes a checklist. Here it is, prioritized, for the two people who have to act on it.

For the defender, the order matters as much as the items. Inventory first: run Akamai's `Get-BadSuccessorOUPermissions.ps1` to learn who can create dMSAs and in which OUs, because you cannot prune what you have not measured [@akamai-readme]. Then reclassify: dMSA-creation rights -- CreateChild for the dMSA class, plus GenericAll, WriteDACL, WriteOwner, or ownership on OUs *and* containers -- are a Tier Zero permission, and they should be pruned to Tier Zero principals just like domain-controller logon rights, as our [AD tiering article](/blog/who-is-allowed-to-log-in-where-the-kdc-side-answer-to-creden/) argues.

Then patch your Windows Server 2025 domain controllers to build 26100.4946 via KB5063878 to close the one-way escalation [@kb5063878]. Finally, make the invisible visible: pre-place auditing SACLs so Events 5136 and 5137 actually fire on the succession attributes and on `msDS-GroupMSAMembership`, watch dMSA ticket requests (Event 4769) [@event-4769], and deploy the Microsoft Defender for Identity alert `xdr_SuspiciousDmsaAction` [@audit-ds-changes] [@mdi-xdr-alerts].

> **Note:** The single most durable action is not the patch -- it is reclassification. A permission that yields Domain Admin is a Tier Zero permission, whatever the object class it nominally applies to. Prune CreateChild, GenericAll, WriteDACL, WriteOwner, and ownership on OUs and containers down to Tier Zero principals, and the 91% collapses regardless of the KDC's behavior [@specterops-badsuccessor] [@akamai-readme].

Where you cannot patch immediately, interim access-control mitigations exist: Jim Sykora's `Add-BadSuccessorOUDenyACEs.ps1` applies three ACEs per OU -- deny Authenticated Users the CreateChild of dMSA objects, restrict `OwnerRights` to replace the implicit WriteDACL, and deny writes to the succession link -- and the KB5008383 `dSHeuristics` flags 28 and 29 harden LDAP-Add authorization and disable implicit owner rights on computer-derived classes [@jimsycurity-dmsas] [@kb5008383] [@ms-adts-ldap-add].

> **Note:** The Deny-ACE mitigations bite on the *staging* step, so they help when an attacker must rely on implicit owner rights. But if the attacker already holds WriteDACL on the OU, every Deny ACE is, in SpecterOps' words, moot -- they can simply rewrite the DACL first. Treat these as pre-patch risk reduction, never as a substitute for pruning the rights or patching the KDC [@specterops-badsuccessor].

| Priority | Action | Why | Source |
|---|---|---|---|
| 1 | Inventory dMSA-creation rights with the audit script | Find who can stage it before changing anything | [@akamai-readme] |
| 2 | Reclassify those rights as Tier Zero and prune them | The 91% is an ACL-hygiene problem the patch never touches | [@specterops-badsuccessor] |
| 3 | Patch Server 2025 DCs to build 26100.4946 (KB5063878) | Closes the one-way KDC escalation | [@kb5063878] |
| 4 | Pre-place SACLs; monitor Events 5136, 5137, and 4769 | The only durable signal is the anomalous directory write | [@audit-ds-changes] [@event-4769] |
| 5 | Deploy MDI `xdr_SuspiciousDmsaAction` | Behavioral coverage without custom engineering | [@mdi-xdr-alerts] |
| 6 | Interim Deny ACEs plus `dSHeuristics` flags 28 and 29 | Reduce exposure before patching, with known gaps | [@jimsycurity-dmsas] [@kb5008383] |

For the operator working an assumed-breach or red-team engagement, the mirror-image checklist is shorter. Confirm the environmental gate before spending any effort: at least one Windows Server 2025 domain controller and a generated KDS root key [@sharpsuccessor]. Discover the permission with the same audit logic a defender would run. And understand the trajectory: this is a post-2025-DC-adoption concern whose reach grows as Windows Server 2025 spreads, not a legacy technique on its way out [@sharpsuccessor].

<Spoiler kind="hint" label="Minimal reproduction preconditions">
To validate BadSuccessor in a lab, you need: at least one Windows Server 2025 domain controller; a generated KDS root key (`Add-KdsRootKey`); a low-privileged principal with CreateChild for the dMSA class (or GenericAll/WriteDACL/WriteOwner/ownership) on one OU; a principal you control to place in `msDS-GroupMSAMembership`; and a Windows Server 2025 or Windows 11 24H2 host to request the dMSA ticket. Pre-patch domain controllers demonstrate the escalation; patched ones (build 26100.4946 and later) demonstrate the mutual-link rejection [@sharpsuccessor] [@kb5063878].
</Spoiler>

Finally, the pitfalls, because most of the wrong reactions to BadSuccessor are predictable: assuming every domain is exposed (it is not -- mind the gate); assuming CreateChild is the only door (GenericAll, WriteDACL, WriteOwner, and ownership are equivalent doors); trusting a root-level Deny ACE (moot if the attacker holds WriteDACL); expecting the ticket to look malicious (it never will); auditing without SACLs (you will see nothing); and assuming the target must log in or be modified (it is a bystander throughout).

The mitigation is identity hygiene, not "turn off dMSA." The account type is a genuine improvement, and it does defeat kerberoasting; the flaw was in succession authorization, not in the account. Which leaves the sharp questions readers keep asking -- and the one sentence this whole story comes down to.

## 11. Frequently Asked Questions

<FAQ title="Frequently asked questions">
<FAQItem question="Is every Active Directory domain vulnerable to BadSuccessor?">
No. It requires at least one Windows Server 2025 domain controller and a generated KDS root key in the domain. At disclosure, Tenable estimated only about 0.7% of Active Directory domains met that bar [@helpnet-patch]. The mechanism is severe, but the qualifying population was small and grows only as Windows Server 2025 is adopted.
</FAQItem>
<FAQItem question="It is patched, so it is gone, right?">
Not entirely. CVE-2025-53779 makes the KDC require a mutual succession link at ticket time, which closes the one-way instant-escalation vector [@akamai-patch]. But the enforcement lives in the KDC, not in the directory: the succession attribute is still writable, dMSA-based credential-acquisition and lateral-movement residuals persist under some conditions, and the over-broad OU permissions that made 91% of environments stageable are untouched by a Kerberos patch [@akamai-patch].
</FAQItem>
<FAQItem question="Does this mean dMSA is insecure -- should I stop using it?">
No. The account type's security goals are sound, and it genuinely defeats kerberoasting by holding a machine-bound secret only on the domain controller [@dmsa-overview]. The flaw was in succession authorization -- the KDC trusting a link without checking consent -- not in the account type. Keep dMSA; fix the permissions and patch the KDC.
</FAQItem>
<FAQItem question="Do you need Domain Admin to run BadSuccessor?">
No, and that is the point. It needs a single OU permission: CreateChild for the `msDS-DelegatedManagedServiceAccount` class, or any ownership, GenericAll, WriteDACL, or WriteOwner right that yields it [@akamai-readme] [@specterops-badsuccessor]. A helpdesk-grade delegation is enough.
</FAQItem>
<FAQItem question="Is the target account modified, or does it have to log in?">
No on both counts. The target is never opened, read, or written, and it does not participate in the forged migration at all -- the attacker writes only their own new dMSA object [@akamai-readme] [@specterops-badsuccessor]. This is exactly why target-object-centric detections and integrity controls miss it.
</FAQItem>
<FAQItem question="Is this just a Golden Ticket or DCSync by another name?">
No. Golden Ticket presupposes you already hold the krbtgt key, and DCSync presupposes the two directory-replication rights -- both are near-total-compromise starting points [@mitre-t1558-001] [@mitre-t1003-006]. BadSuccessor starts from one OU access-control entry and produces impersonation and key theft without either prerequisite.
</FAQItem>
<FAQItem question="dMSA versus gMSA -- what actually differs?">
A dMSA's secret is machine-bound and lives only on the domain controller, where it "can't be retrieved or found anywhere other than on the DC." A gMSA's password is machine-*retrievable* by any authorized host, and Microsoft states plainly that gMSA passwords "are still not machine bound and can be stolen" [@dmsa-overview]. That retrievability is the residual dMSA was built to remove.
</FAQItem>
</FAQ>

## The Sentence It Comes Down To

Trace the whole arc and the thesis stops being a slogan and becomes a conclusion. Service accounts were the softest target in Active Directory because their secrets were human-chosen and crackable offline, which is what kerberoasting weaponized [@irongeek-derbycon]. Sixteen years of engineering -- sMSA, then gMSA, then dMSA -- drove the secret out of human hands, then off the member host, then onto the domain controller alone [@gmsa-overview] [@dmsa-overview].

The final step, dMSA, added the one thing everyone still wanted: a one-click migration. To make that migration seamless, the KDC was taught to honor a succession link. And because the KDC honored the link without ever checking that the superseded account consented, the very feature engineered to end service-account theft handed a low-privileged user the ability to inherit any account's identity and keys -- Domain Admin included -- from a single permission on a single forgotten OU [@specterops-badsuccessor] [@akamai-disclosure].

The honest qualifiers are the ones that make the claim precise rather than sensational. The exposure was conditional: a Windows Server 2025 domain controller and a KDS root key, roughly 0.7% of domains at disclosure [@helpnet-patch]. The window was brief: disclosed in May 2025, closed by CVE-2025-53779 in August [@nvd-cve]. But "brief" and "conditional" do not undo the lesson. A feature can be a real security improvement and ship an escalation primitive in the same box, because the property that makes it convenient and the property that makes it dangerous can be the same property, read two ways.

<PullQuote>
The feature built to end service-account attacks briefly became the cleanest domain takeover in years. The patch closed the window. The lesson -- that a convenience feature can carry an escalation primitive inside it -- outlives the patch.
</PullQuote>

That is why dMSA-creation rights belong in Tier Zero, why "watch the write, not the ticket" is the detection rule, and why the next feature that lets one account inherit another's power deserves the question the KDC never asked: says who?

<StudyGuide slug="badsuccessor-dmsa" keyTerms={[
  { term: "dMSA", definition: "Delegated Managed Service Account (Windows Server 2025); a machine-bound secret held only on the domain controller, with a supervised in-place migration." },
  { term: "gMSA", definition: "Group Managed Service Account (2012); its password is derived from the KDS root key and is retrievable by authorized hosts, not machine-bound." },
  { term: "KDS Root Key", definition: "A domain secret from which gMSA and dMSA managed passwords derive; its presence is one of the two BadSuccessor preconditions." },
  { term: "PAC", definition: "Privilege Attribute Certificate; the KDC-signed authorization payload inside a Kerberos ticket that carries SIDs and group memberships." },
  { term: "msDS-ManagedAccountPrecededByLink", definition: "The dMSA succession link naming the account it supersedes; the pre-patch KDC trusted it without checking consent." },
  { term: "Kerberoasting", definition: "Offline cracking of a service account's password-derived key from a requested service ticket (Tim Medin, DerbyCon 2014)." },
  { term: "Clean Source Principle", definition: "Only a subject at least as trusted as an object may control it; BadSuccessor violates it by letting a non-Tier-Zero right yield Domain Admin." },
  { term: "CVE-2025-53779", definition: "The August 2025 Windows Kerberos fix that makes the KDC require a mutual succession link at ticket time." }
]} />
