Skip to content

Add gMSA Cypher queries for BloodHound CE#49

Open
chryzsh wants to merge 1 commit intoSpecterOps:mainfrom
chryzsh:gmsa-queries
Open

Add gMSA Cypher queries for BloodHound CE#49
chryzsh wants to merge 1 commit intoSpecterOps:mainfrom
chryzsh:gmsa-queries

Conversation

@chryzsh
Copy link
Copy Markdown

@chryzsh chryzsh commented Mar 8, 2026

Add four queries for enumerating and analyzing Group Managed Service Accounts (gMSAs) and ReadGMSAPassword relationships:

  • All gMSAs: List all gMSA accounts
  • All ReadGMSAPassword relationships: Show all ReadGMSAPassword edges
  • Principals with ReadGMSAPassword: Reader and target pairs
  • Effective gMSA password readers through group membership: Nested group traversal

Add four queries for enumerating and analyzing Group Managed Service
Accounts (gMSAs) and ReadGMSAPassword relationships:

- All gMSAs: List all gMSA accounts
- All ReadGMSAPassword relationships: Show all ReadGMSAPassword edges
- Principals with ReadGMSAPassword: Reader and target pairs
- Effective gMSA password readers through group membership: Nested group traversal
@martinsohn martinsohn self-assigned this Apr 4, 2026
@martinsohn
Copy link
Copy Markdown
Collaborator

Hi @chryzsh, thanks for wanting to add more gMSA visibility!

I suggest we change them to these. What do you think?

First, relying on the gmsa property will include gMSAs where no incoming ReadGMSAPassword edge exists:

name: All enabled Group Managed Service Accounts (gMSAs)
guid: 0fc16935-14b7-4859-9a2a-a191daa4c081
prebuilt: false
platforms: Active Directory
category: Active Directory Hygiene
description: List all enabled Group Managed Service Accounts (gMSAs).
query: |-
  MATCH (g:Base)
  WHERE g.gmsa = true
  AND g.enabled = true
  RETURN g
  LIMIT 1000
revision: 1
resources: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts/group-managed-service-accounts-overview
acknowledgements: crusher, @chryzsh
image

Second, a query that captures the same as the three queries:

  • queries/All ReadGMSAPassword relationships.yml
  • queries/Effective gMSA password readers through group membership.yml
  • queries/Principals with ReadGMSAPassword.yml
name: Principals that can read Group Managed Service Accounts (gMSAs) passwords
guid: 10d0ee8e-17ec-4f6c-9b94-8dffe548f9d4
prebuilt: false
platforms: Active Directory
category: Active Directory Hygiene
description: Finds principals with ReadGMSAPassword edges over gMSAs, including rights derived through nested group memberships.
query: |-
  MATCH p1 = (s1:Base)-[:ReadGMSAPassword]->(d1:Base)
  WHERE s1<>d1
  AND d1.gmsa = true
  MATCH p2 = (s2:Base)-[:MemberOf*1..]->()-[:ReadGMSAPassword]->(d2:Base)
  WHERE s2<>d2
  AND d2.gmsa = true
  RETURN p1, p2
revision: 1
resources: https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts/group-managed-service-accounts-overview
acknowledgements: crusher, @chryzsh
image

@chryzsh
Copy link
Copy Markdown
Author

chryzsh commented Apr 4, 2026

For the first one, this looks like a solid suggestion. I still think it would be convenient to have a "table" type query that just lists all of them, but I understand if you want to keep the queries focus on path finding.

Second, good suggestion to consolidate the three queries into one.

I'm fine with you making these changes yourself before merging, lest you want me to do it.

@martinsohn
Copy link
Copy Markdown
Collaborator

Cool. I'll add the queries in an upcoming larger addition. I'll keep this PR open for now.

@martinsohn
Copy link
Copy Markdown
Collaborator

martinsohn commented Apr 4, 2026

@chryzsh I just realized that I had planned on creating a similar query, which filters out Tier Zero source principals too (as they can compromise anything anyway).

Please do let me know if you have feedback to it:

name: Non-Tier Zero principals with access to enabled gMSA passwords
guid: 10d0ee8e-17ec-4f6c-9b94-8dffe548f9d4
prebuilt: false
platforms: Active Directory
category: Active Directory Hygiene
description: Finds non-Tier Zero principals that can read Group Managed Service Account (gMSA) passwords, or modify the msDS-GroupMSAMembership property controlling read access. Unauthorized access to gMSA passwords allows an attacker to authenticate as the service account and access any resource it manages.
query: |-
  MATCH p1=(s1:Base)-[r:ReadGMSAPassword|GenericAll|GenericWrite|WriteOwner|WriteDacl]->(d1:Base)
  WHERE s1<>d1
  AND d1.gmsa = true
  AND d1.enabled= true
  // Exclude Tier Zero principals
  AND NOT ((s1:Tag_Tier_Zero) OR COALESCE(s1.system_tags, '') CONTAINS 'admin_tier_0')
  MATCH p2 = (s2:Base)-[:MemberOf*1..]->()-[:ReadGMSAPassword]->(d2:Base)
  WHERE s2<>d2
  AND d2.gmsa = true
  AND d2.enabled= true
  // Exclude Tier Zero principals
  AND NOT ((s2:Tag_Tier_Zero) OR COALESCE(s2.system_tags, '') CONTAINS 'admin_tier_0')
  RETURN p1,p2
revision: 1
resources:
  - https://learn.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview
acknowledgements:
- Martin Sohn Christensen, @martinsohndk
- crusher, @chryzsh

@chryzsh
Copy link
Copy Markdown
Author

chryzsh commented Apr 4, 2026

This looks like a good evolution of the query, especially filtering out Tier Zero principles (like I did in my other PR). Adding Generic* edges in p1 is probably a good idea.

It seems like the p2 path (transitive via group membership?) only checks for ReadGMSAPassword, not the write-based edges (GenericAll, etc.). Maybe someone could also have transitive GenericWrite over a gMSA through group membership? Or are direct group-to-gMSA write permissions less common? Also, will adding all those edge types to p2 would make the query heavier?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants