ReadGMSAPassword: reading a managed service account's password straight from the directory

  • active-directory
  • gmsa
  • credential-access
  • acl-abuse
  • detection

Group Managed Service Accounts are the right answer to a real problem. A traditional service account has a password a human picked, so it is guessable, it rarely rotates, and it leaks through Kerberoasting. A gMSA has none of that: Active Directory generates and stores a 240-byte managed password, member hosts fetch it when they need it, and it rotates on a schedule with nobody typing it. So gMSAs defeat offline cracking by construction. The catch is not in the cryptography, it is in the authorization: the directory lets you nominate exactly which principals may retrieve the managed password, and when that list is drawn too wide, reading the password becomes one LDAP query. This is the ReadGMSAPassword abuse, and it is one link in the over-privileged service-account chain.

What you will learn

  • What a gMSA actually protects, and the one thing it does not.
  • Why reading a managed password is worse for a defender than cracking a normal one.
  • How to read the blob and turn it into access, step by step.
  • How to build a gMSA in a lab and read it with a deliberately over-broad list, then watch the fix work.
  • The detection signal and the single ACL that closes the technique.

Prerequisites and scope: you hold the credentials of a principal that appears in a gMSA's retrieval list (directly or through a group). Everything here is a directory permission, not a bug, so it closes to tightening that list, not a patch.

The mental model

Imagine a safe whose combination changes itself every few weeks to a long random number nobody could guess. That is the gMSA password, and against a safecracker (offline cracking) it is excellent. But the safe has a side panel with a list of names, and anyone on that list can simply ask the building and be told the current combination, no cracking involved. The security of the safe now rests entirely on who is on that list. gMSAs move the risk from "can you guess the password" to "who may be handed it", and defenders who celebrate the unguessable password often forget to audit the list.

Why the weakness exists

A gMSA stores its current and previous password in a protected attribute, msDS-ManagedPassword. That attribute is gated by msDS-GroupMSAMembership, surfaced in tooling as the PrincipalsAllowedToRetrieveManagedPassword property. Any principal on that list can fetch the blob from a DC and compute the account's NT hash from it.

The intent is sound: the hosts that run the service need the password, so they go on the list. The failure is operational. The list gets a broad group ("all admins", a catch-all service group, a stale group that once made sense) instead of just the machine accounts that host the service. From then on, compromising any member of that group yields the gMSA's hash directly, with three properties that are worse than cracking:

  • No cracking. You read the current hash; 240 bytes of randomness is irrelevant when you are handed the result.
  • No lockout, no noise on the account. It is a directory read, not an authentication, so there is no bad-password counter to trip.
  • It keeps rotating to you. While you stay on the list, every rotation hands you the new hash the next time you ask.

That is the whole weakness: the strongest service-account password in the directory is only as protected as the ACL that says who may read it.

How it works, step by step

You need one credential for a principal on the retrieval list and LDAP reach to a DC.

Step 1: read the blob

nxc ldap 10.10.10.10 -u listed_user -p Password1 --gmsa
#   -> gmsa_svc$   NTLM <nthash>

Other front ends do the same read. gMSADumper.py is the dedicated tool; bloodyAD reads it attribute-first:

python3 gMSADumper.py -u listed_user -p Password1 -d CORP.LOCAL
bloodyAD -u listed_user -p Password1 -d CORP.LOCAL --host 10.10.10.10 \
  get object 'gmsa_svc$' --attr msDS-ManagedPassword

Step 2: use the hash

The NT hash is all you need to authenticate as the gMSA by pass-the-hash:

nxc smb   10.10.10.10 -u gmsa_svc$ -H <nthash>
nxc winrm 10.10.10.10 -u gmsa_svc$ -H <nthash>

Step 3: enumerate what the account can do

This is the step learners skip. A gMSA hash is only worth what the account is entitled to, so the moment you have it, enumerate its groups and rights. If it is in a built-in privileged group, you are not done, you are one step from the DC. See the amplifier below.

Why the gMSA is often worth more than it looks

A service account's value is whatever it can do, and gMSAs are frequently over-entitled for convenience. The common amplifier is a gMSA placed in a built-in privileged group. If it is in BUILTIN\Server Operators on a DC, the pass-the-hash WinRM logon above lands with a token carrying SeBackupPrivilege, which reads the directory database itself. Why that group is tier-0 is Server Operators to Domain Admin; the database read is SeBackupPrivilege on a domain controller. So the gMSA read is rarely the end: it is the step that converts a weak ACL into whatever the account's membership allows.

BloodHound draws the ReadGMSAPassword edge directly, so attacker and defender find it the same way.

Build it in a lab

Prove the whole thing on a DC you own:

  1. Create a gMSA. On a lab DC, add the KDS root key once (Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10)) so it is usable immediately in a lab), then:
    New-ADServiceAccount gmsa_svc -DNSHostName gmsa_svc.corp.local `
      -PrincipalsAllowedToRetrieveManagedPassword 'Domain Admins'
    
    Using Domain Admins here is the deliberately over-broad list that creates the weakness.
  2. Give yourself a listed principal. Use (or create) an account that is in the group you put on the retrieval list.
  3. Read it from Kali with nxc ldap ... --gmsa and watch the NT hash come back.
  4. Fix it and retry. Reset the list to a single machine account: Set-ADServiceAccount gmsa_svc -PrincipalsAllowedToRetrieveManagedPassword 'LABDC$'. Rerun the read as your user and watch it return nothing. That before-and-after is the lesson.

Detection

  • LDAP reads of msDS-ManagedPassword. Event 4662 referencing that property or the gMSA object, from a principal that is not the service's own hosts, is the direct tell. It needs object-access auditing with a SACL on the gMSA objects, which is not on by default.
  • Pass-the-hash logons for the gMSA from the wrong source. A gMSA should authenticate only from its member hosts; a logon (4624 type 3, or a WinRM/4648 pattern) from an operator workstation or a Kali-shaped source is anomalous by definition.
  • Retrieval-list changes. Writes to msDS-GroupMSAMembership (event 5136) are rare in normal operation; alert on them, especially additions of broad groups.
  • Honeypot gMSA. A decoy gMSA with a tempting name and a monitored group on its retrieval list is a high-fidelity tripwire: any read of its password is an attacker, because no real service fetches it.

Prevention and response

  • Scope the retrieval list to hosts, not people. It should contain the exact machine accounts (or a tight group of them) that run the service, nothing else. This single change closes the technique.
  • Treat the retrieval list as a tier-0 ACL. Audit it like Domain Admins membership, on a schedule, against BloodHound output.
  • Do not put service accounts in built-in privileged groups. Grant the one right the service needs; never hand it Server Operators or Backup Operators for convenience, which is what keeps a read of the hash from becoming domain compromise.
  • Response after a confirmed read. Treat the gMSA as compromised: trigger a managed-password rotation, review everywhere it authenticates and what its memberships reach, and remove it from any privileged group it should never have been in.

Check yourself

  1. In the safe analogy, what part is strong and what part is the weakness?
  2. Why is reading a gMSA password worse for a defender than an attacker cracking a weak service-account password?
  3. You read a gMSA hash and pass-the-hash works, but you have no special access. What is the next thing to check, and why?
  4. What is the single configuration change that closes this technique, and why does it work?

Answers:

  1. The password itself (long, random, auto-rotating) is strong; the retrieval-list ACL that decides who may be handed it is the weakness.
  2. Cracking is noisy and bounded by password strength; reading is a silent directory operation, unaffected by password strength, and keeps delivering the new hash after each rotation while you stay on the list.
  3. Enumerate the account's group memberships and privileges. A gMSA is only worth its entitlements, and a built-in privileged group membership turns the read into a path to the DC.
  4. Restrict PrincipalsAllowedToRetrieveManagedPassword to the service's own host accounts. It works because the DC checks that list before returning the blob, so no other principal can read it.

Use

Authorized and educational use only: your own lab, a directory you own, or an engagement with written permission. gMSAs are a genuine improvement and this is not an argument against them; it is an argument for auditing the one ACL that decides who may read them. Tools are named rather than carried, and the piece is paired with detection and remediation.

References

Back to all techniques