From 05200c712229fa06d5cbc6c41467119d24b4ac6c Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 7 Oct 2025 22:16:13 +0200 Subject: [PATCH 1/4] Remove role condition for Tier Zero specific query --- ... paths from Entra Users to Tier Zero High Value targets.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml b/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml index 3f3024a..a5495da 100644 --- a/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml +++ b/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml @@ -6,8 +6,7 @@ category: Shortest Paths description: query: |- MATCH p=shortestPath((s:AZUser)-[:AZ_ATTACK_PATHS*1..]->(t:AZBase)) - WHERE (t:AZBase) AND t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator' AND s<>t - AND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + WHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') RETURN p LIMIT 1000 revision: 2 From b133b13612cc4adb17379f7b312e18ea14dab4b6 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 7 Oct 2025 22:16:38 +0200 Subject: [PATCH 2/4] Add condition for AZRole 'Privileged Role Administrator' --- queries/All members of high privileged roles.yml | 2 +- queries/Shortest paths to privileged roles.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/queries/All members of high privileged roles.yml b/queries/All members of high privileged roles.yml index b056e28..a58e59f 100644 --- a/queries/All members of high privileged roles.yml +++ b/queries/All members of high privileged roles.yml @@ -6,7 +6,7 @@ category: General description: query: |- MATCH p=(t:AZRole)<-[:AZHasRole|AZMemberOf*1..2]-(:AZBase) - WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator' + WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator' RETURN p LIMIT 1000 revision: 1 diff --git a/queries/Shortest paths to privileged roles.yml b/queries/Shortest paths to privileged roles.yml index 52b33b6..5e74b6d 100644 --- a/queries/Shortest paths to privileged roles.yml +++ b/queries/Shortest paths to privileged roles.yml @@ -6,7 +6,7 @@ category: Shortest Paths description: query: |- MATCH p=shortestPath((s:AZBase)-[:AZ_ATTACK_PATHS*1..]->(t:AZRole)) - WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator' AND s<>t + WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator' AND s<>t RETURN p LIMIT 1000 revision: 2 From 17f21566c229a5f47f5c8dd00b5ee296727fa907 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 7 Oct 2025 22:19:10 +0200 Subject: [PATCH 3/4] revision bump --- queries/All members of high privileged roles.yml | 2 +- ...t paths from Entra Users to Tier Zero High Value targets.yml | 2 +- queries/Shortest paths to privileged roles.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/queries/All members of high privileged roles.yml b/queries/All members of high privileged roles.yml index a58e59f..189167a 100644 --- a/queries/All members of high privileged roles.yml +++ b/queries/All members of high privileged roles.yml @@ -9,7 +9,7 @@ query: |- WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator' RETURN p LIMIT 1000 -revision: 1 +revision: 2 resources: acknowledgements: diff --git a/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml b/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml index a5495da..f653464 100644 --- a/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml +++ b/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml @@ -9,7 +9,7 @@ query: |- WHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') RETURN p LIMIT 1000 -revision: 2 +revision: 3 resources: acknowledgements: diff --git a/queries/Shortest paths to privileged roles.yml b/queries/Shortest paths to privileged roles.yml index 5e74b6d..664f332 100644 --- a/queries/Shortest paths to privileged roles.yml +++ b/queries/Shortest paths to privileged roles.yml @@ -9,7 +9,7 @@ query: |- WHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator' AND s<>t RETURN p LIMIT 1000 -revision: 2 +revision: 3 resources: acknowledgements: From 0a3c158c139a64f928a70fe42ba0f7435b37fc65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Oct 2025 20:23:05 +0000 Subject: [PATCH 4/4] Update combined queries --- Queries.json | 2304 +++++++++++++++++++++++++------------------------- 1 file changed, 1152 insertions(+), 1152 deletions(-) diff --git a/Queries.json b/Queries.json index 30a1005..168cbd7 100644 --- a/Queries.json +++ b/Queries.json @@ -1,4 +1,48 @@ [ + { + "name": "CA administrators and CA managers", + "guid": "fd35e3d8-0c74-4b5a-a847-c0dd1f1c9f19", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Certificate Services", + "description": null, + "query": "MATCH p = (:Base)-[:ManageCertificates|ManageCA]->(:EnterpriseCA)\nRETURN p\nLIMIT 1000", + "revision": 1, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Principals with passwords stored using reversible encryption", + "guid": "ab900835-b2b8-4674-87b4-8b5141e80439", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Hygiene", + "description": null, + "query": "MATCH (n:Base)\nWHERE n.encryptedtextpwdallowed = true\nRETURN n", + "revision": 1, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Tier Zero users with email", + "guid": "9654c0d4-f1e8-4393-a2d1-53a5554a9de8", + "prebuilt": false, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Hygiene", + "description": "Tier Zero accounts with email access have an increased attack surface.", + "query": "MATCH (n)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.email <> \"\"\nAND n.enabled = true\nAND NOT toUpper(n.email) ENDS WITH \".ONMICROSOFT.COM\"\nAND NOT (\n (toUpper(n.email) STARTS WITH \"HEALTHMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHDISCOVERYMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHDISCOVERY\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHAPPROVAL\"\n OR toUpper(n.email) STARTS WITH \"FEDERATEDEMAIL\"\n OR toUpper(n.email) STARTS WITH \"SYSTEMMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MIGRATION.\")\n AND\n (n.name STARTS WITH \"SM_\"\n OR n.name STARTS WITH \"HEALTHMAILBOX\")\n)\nRETURN n", + "revision": 1, + "resources": [], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] + }, { "name": "Computers without Windows LAPS", "guid": "7c50f724-c467-4005-8e3f-9a6ce1461db0", @@ -18,15 +62,33 @@ ] }, { - "name": "Domains with functional level not the latest version", - "guid": "3da9d14a-f1cb-4df7-b3da-8d73ff5c401b", + "name": "Foreign Service Principals With Group Memberships", + "guid": "327ef6a5-bfa8-4c92-b35a-d3df85264a24", + "prebuilt": false, + "platforms": [ + "Azure" + ], + "category": "Azure Hygiene", + "description": "Review each to validate whether their presence is expected and whether the assigned group memberships are appropriate for the foreign service principal.", + "query": "MATCH p = (sp:AZServicePrincipal)-[:AZMemberOf]->(g:AZGroup)\nWHERE toUpper(sp.appownerorganizationid) <> toUpper(g.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", + "revision": 1, + "resources": [ + "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" + ], + "acknowledgements": [ + "Stephen Hinck" + ] + }, + { + "name": "All incoming and local paths for a specific computer", + "guid": "1f67e538-19d4-4020-89c8-5b39b31571bd", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": null, - "query": "MATCH (n:Domain)\nWHERE toString(n.functionallevel) IN ['2008','2003','2003 Interim','2000 Mixed/Native']\nRETURN n", + "category": "Domain Information", + "description": "All incoming and local paths for a specific computer; incoming from domain objects and paths local inside the computer.", + "query": "// Replace 'HOSTNAME' with the computer's shortname eg. 'SRV01', not FQDN\nMATCH p=(n:Base)-[:RemoteInteractiveLogonPrivilege|AdminTo|CanRDP|LocalToComputer|MemberOfLocalGroup]-(m:Base)\nWHERE m.name CONTAINS 'HOSTNAME'\nAND m.name CONTAINS '.' // Only see computer-related objects (eg. not AD Groups)\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -34,15 +96,15 @@ ] }, { - "name": "Kerberos-enabled service account member of built-in Admins groups", - "guid": "42a856fc-257a-4142-9592-ca95fd49e579", + "name": "Non-Tier Zero account with unconstrained delegation", + "guid": "e7e9a927-3f34-42c7-b921-d8bcf626011e", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Base)-[:MemberOf*1..]->(g:Group)\nWHERE (\n g.objectid ENDS WITH '-512' // Domain Admins\n OR g.objectid ENDS WITH '-519' // Enterprise Admins\n OR g.objectid ENDS WITH '-518' // Schema Admins\n)\nAND n.hasspn = true\nRETURN p", + "query": "MATCH (n:Base)\nWHERE n.unconstraineddelegation = true\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [ @@ -50,38 +112,44 @@ ] }, { - "name": "Shortest paths to privileged roles", - "guid": "3dc73dd8-4873-4aeb-a88f-56a58c77f512", - "prebuilt": true, + "name": "Circular AZ group memberships", + "guid": "b005669c-d8af-47ae-a0f1-4f36cd5334ab", + "prebuilt": false, "platforms": [ "Azure" ], - "category": "Shortest Paths", - "description": null, - "query": "MATCH p=shortestPath((s:AZBase)-[:AZ_ATTACK_PATHS*1..]->(t:AZRole))\nWHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator' AND s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], - "acknowledgements": [] + "category": "Azure Hygiene", + "description": "Detects circular group membership chains where groups are members of themselves through one or more intermediate groups. This causes an administrative complexity.", + "query": "MATCH p=(x:AZGroup)-[:AZMemberOf*2..]->(y:AZGroup)\nWHERE x.objectid=y.objectid\nRETURN p\nLIMIT 100", + "revision": 1, + "resources": [ + "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Tier Zero users with passwords not rotated in over 1 year", - "guid": "5e0d69b1-37d1-43ae-ac5d-f297f312fab5", + "name": "Non-Tier Zero principals with BadSuccessor rights (no prerequisites check)", + "guid": "2b9fb71e-73ad-4061-a2df-40c7132b044d", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": null, - "query": "WITH 365 as days_since_change\nMATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0')\nAND u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u\nLIMIT 100", + "category": "Dangerous Privileges", + "description": "Finds non-Tier Zero principals with BadSuccessor rights with no prerequisites check (DC2025 & KDC key).", + "query": "// Find OU control\nMATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base)\n// Exclude Tier Zero\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p LIMIT 1000", "revision": 1, - "resources": [], + "resources": [ + "https://bsky.app/profile/specterops.io/post/3lpua65qeu22l" + ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "On-Prem Users synced to Entra Users with Azure RM Roles (group delegated)", - "guid": "e4f2eada-8a89-4ba9-89eb-abbee4efbc7a", + "name": "On-Prem Users synced to Entra Users that Own Entra Objects", + "guid": "4baf1026-e64c-4e31-afeb-2090b8090130", "prebuilt": true, "platforms": [ "Active Directory", @@ -89,35 +157,37 @@ ], "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase)\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwns]->(:AZBase)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled", - "guid": "96e70597-2d74-4503-a624-f1e30b642894", - "prebuilt": true, + "name": "Domains without Microsoft LAPS computers", + "guid": "f9b440b5-732c-4ed3-b6d2-83857db17e1a", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "Domain Information", "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(eca:EnterpriseCA)\nWHERE eca.isuserspecifiessanenabled = True\nRETURN p\nLIMIT 1000", + "query": "MATCH (d:Domain)\nOPTIONAL MATCH (c:Computer)\nWHERE c.domainsid = d.objectid AND c.haslaps = true\nWITH d, COLLECT(c) AS computers\nWHERE SIZE(computers) = 0\nRETURN d", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Domains allowing authenticated domain enumeration", - "guid": "1e1e6fdd-6973-4547-906c-a494b5fbdcba", + "name": "Accounts with SID History to a same-domain account", + "guid": "275d2d58-0cad-4cad-8103-e0874cece666", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE n.objectid ENDS WITH \"S-1-5-11\" // Authenticated Users\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", + "query": "MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE n.domainsid = m.domainsid\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -125,15 +195,15 @@ ] }, { - "name": "Unresolved SID with outbound control", - "guid": "4e8429f9-cba2-41e9-bac6-0c42f96b2c57", + "name": "Domains allowing authenticated domain enumeration", + "guid": "1e1e6fdd-6973-4547-906c-a494b5fbdcba", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Base)-[r]->(:Base)\nWHERE r.isacl\nAND n.name CONTAINS \"S-1-5-21-\" // Unresolved SID\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE n.objectid ENDS WITH \"S-1-5-11\" // Authenticated Users\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -141,15 +211,15 @@ ] }, { - "name": "Large default groups with outbound control of OUs", - "guid": "310b3626-f8e6-4ab0-832c-72df6048597f", + "name": "All Operators", + "guid": "3dfd0843-1ff9-4c21-aa67-feae08d109de", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Domain Information", "description": null, - "query": "MATCH p=(n:Group)-[]->(:OU)\nWHERE n.objectid ENDS WITH \"-513\" // DOMAIN USERS\nOR n.objectid ENDS WITH \"-515\" // DOMAIN COMPUTERS\nOR n.objectid ENDS WITH \"-S-1-5-11\" // AUTHENTICATED USERS\nOR n.objectid ENDS WITH \"-S-1-1-0\" // EVERYONE\nOR n.objectid ENDS WITH \"S-1-5-32-545\" // USERS\nOR n.objectid ENDS WITH \"S-1-5-32-546\" // GUESTS\nOR n.objectid ENDS WITH \"S-1-5-7\" // ANONYMOUS\nRETURN p", + "query": "MATCH p=(:Base)-[:MemberOf]->(n:Group)\nWHERE (\n n.objectid ENDS WITH 'S-1-5-32-551' OR // Backup Operators\n n.objectid ENDS WITH 'S-1-5-32-556' OR // Network Configuration Operators\n n.objectid ENDS WITH 'S-1-5-32-549' OR // Server Operators\n n.objectid ENDS WITH 'S-1-5-32-579' OR // Access Control Assistance Operators\n n.objectid ENDS WITH 'S-1-5-32-548' OR // Account Operators\n n.objectid ENDS WITH 'S-1-5-32-569' OR // Cryptographic Operators\n n.objectid ENDS WITH 'S-1-5-32-550' // Print Operators\n)\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -157,74 +227,66 @@ ] }, { - "name": "Shortest paths to Tier Zero / High Value targets", - "guid": "237aac58-8641-4703-a9f7-001d69546fd8", + "name": "All coerce and NTLM relay edges", + "guid": "15c5ff3b-856c-44d1-a731-a8cb72512dd1", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH p=shortestPath((s)-[:AD_ATTACK_PATHS*1..]->(t:Tag_Tier_Zero))\nWHERE s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], + "query": "MATCH p = (n:Base)-[:CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|CoerceAndRelayNTLMToADCS|CoerceAndRelayNTLMToSMB]->(:Base)\nRETURN p LIMIT 500", + "revision": 1, + "resources": [ + "https://specterops.io/blog/2025/04/08/the-renaissance-of-ntlm-relay-attacks-everything-you-need-to-know/" + ], "acknowledgements": [] }, { - "name": "Domain Controllers allowing NTLMv1 or LM authentication", - "guid": "4b42513c-f89d-47ff-8d98-908af49d2b48", + "name": "Entra ID SSO accounts not rolling Kerberos decryption key", + "guid": "1867abf8-08e3-4ea8-8f65-8366079d35c4", "prebuilt": false, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "NTLM Relay Attacks", - "description": null, - "query": "MATCH (dc:Computer)\nWHERE dc.isdc = true\nAND (dc.lmcompatibilitylevel IS NOT NULL AND NOT dc.lmcompatibilitylevel = 5)\nRETURN dc", + "category": "Configuration Weakness", + "description": "Microsoft highly recommends that you roll over the Entra ID SSO Kerberos decryption key at least every 30 days.", + "query": "MATCH (n:Computer)\nWHERE n.name STARTS WITH \"AZUREADSSOACC.\"\nAND n.pwdlastset < (datetime().epochseconds - (30 * 86400))\nRETURN n", "revision": 1, - "resources": [], + "resources": [ + "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-faq#how-can-i-roll-over-the-kerberos-decryption-key-of-the--azureadsso--computer-account-" + ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Principals with DES-only Kerberos authentication", - "guid": "d03ea1ef-70f0-439b-b1ef-d7f94ceb2af3", - "prebuilt": true, + "name": "Domains with more than 50 Tier Zero accounts", + "guid": "f046e95a-5f84-4e83-bcda-6e83f3d8e21a", + "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Base)\nWHERE n.enabled = true\nAND n.usedeskeyonly = true\nRETURN n", - "revision": 1, - "resources": [], - "acknowledgements": [] - }, - { - "name": "On-Prem Users synced to Entra Users with Azure RM Roles (direct)", - "guid": "8569113b-e42e-49b0-a968-53bcf0ccd970", - "prebuilt": true, - "platforms": [ - "Active Directory", - "Azure" - ], - "category": "Cross Platform Attack Paths", - "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase)\nRETURN p\nLIMIT 1000", + "query": "MATCH (d:Domain)-[:Contains*1..]->(n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nWITH d, COUNT(n) AS adminCount\nWHERE adminCount > 50\nRETURN d", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Domains with List Object mode enabled", - "guid": "05e2a94b-5ee6-47ec-b715-3982f30af01b", + "name": "Domains not mitigating CVE-2021-42291", + "guid": "02202726-d86d-46c2-891c-9770c635f76f", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "Checks the fDoListObject flag of dSHeuristics.", - "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{2}[^0].*\"\nRETURN n", + "category": "Active Directory Hygiene", + "description": "Checks the AttributeAuthorizationOnLDAPAdd flag of dSHeuristics.", + "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \"^(.{0,27}|.{27}[^1].*)$\"\nRETURN n", "revision": 1, "resources": [ "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" @@ -234,96 +296,88 @@ ] }, { - "name": "CA administrators and CA managers", - "guid": "fd35e3d8-0c74-4b5a-a847-c0dd1f1c9f19", + "name": "Foreign principals in Tier Zero / High Value targets", + "guid": "95bec736-86ef-4017-8465-9b9b66548b17", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Active Directory Certificate Services", + "category": "Azure Hygiene", "description": null, - "query": "MATCH p = (:Base)-[:ManageCertificates|ManageCA]->(:EnterpriseCA)\nRETURN p\nLIMIT 1000", + "query": "MATCH (n:AZServicePrincipal)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT toUpper(n.appownerorganizationid) = toUpper(n.tenantid)\nAND n.appownerorganizationid CONTAINS '-'\nRETURN n\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Tier Zero computers with unsupported operating systems", - "guid": "a87b558c-5746-4a90-9f83-c86e7b924a52", - "prebuilt": false, + "name": "On-Prem Users synced to Entra Users with Azure RM Roles (group delegated)", + "guid": "e4f2eada-8a89-4ba9-89eb-abbee4efbc7a", + "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Active Directory Hygiene", + "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH (c:Computer)\nWHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*'\nAND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN c\nLIMIT 100", + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "All ADCS ESC privilege escalation edges", - "guid": "49db8edc-8421-438f-b97b-23c042959bef", - "prebuilt": false, - "platforms": [ + "name": "Shortest paths from Owned objects", + "guid": "e370a01d-c129-4f19-b88d-9479cbe00028", + "prebuilt": true, + "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "Shortest Paths", "description": null, - "query": "MATCH p=(:Base)-[:ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|GoldenCert|CoerceAndRelayNTLMToADCS]->(:Base)\nRETURN p", - "revision": 1, - "resources": [ - "https://posts.specterops.io/certified-pre-owned-d95910965cd2", - "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-1-799f3d3b03cf", - "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-2-ac7f925d1547", - "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-3-33efb00856ac", - "https://posts.specterops.io/adcs-esc13-abuse-technique-fda4272fbd53", - "https://specterops.io/blog/2025/04/08/the-renaissance-of-ntlm-relay-attacks-everything-you-need-to-know/#:~:text=Introducing%20the%20CoerceAndRelayNTLMToADCS%20Edge" - ], - "acknowledgements": [ - "Jonas B\u00fclow Knudsen, @Jonas_B_K" - ] + "query": "MATCH p=shortestPath((s:Base)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE (s:Tag_Owned)\nAND s<>t\nRETURN p\nLIMIT 1000", + "revision": 2, + "resources": [], + "acknowledgements": [] }, { - "name": "Tier Zero / High Value users with non-expiring passwords", - "guid": "4eca1b69-00a2-48a0-abb3-b94ea647cf6b", + "name": "Kerberoastable members of Tier Zero / High Value groups", + "guid": "e6da7800-ae06-41cb-80a6-d5421ab2143a", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Kerberos Interaction", "description": null, - "query": "MATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0') AND u.enabled = true\nAND u.pwdneverexpires = true\nRETURN u\nLIMIT 100", + "query": "MATCH (u:User)\nWHERE (u:Tag_Tier_Zero) AND u.hasspn=true\nAND u.enabled = true\nAND NOT u.objectid ENDS WITH '-502'\nAND NOT COALESCE(u.gmsa, false) = true\nAND NOT COALESCE(u.msa, false) = true \nRETURN u\nLIMIT 100", "revision": 1, - "resources": [], + "resources": [ + "https://attack.mitre.org/techniques/T1558/003/" + ], "acknowledgements": [] }, { - "name": "Principals with foreign domain group membership", - "guid": "8fb3214a-5a75-4ecd-b293-c121abd94b4b", + "name": "Enrollment rights on published enrollment agent certificate templates", + "guid": "8483bf5b-89f1-4723-abb2-c48295f6393e", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p=(s:Base)-[:MemberOf]->(t:Group)\nWHERE s.domainsid<>t.domainsid\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE '1.3.6.1.4.1.311.20.2.1' IN ct.effectiveekus\nOR '2.5.29.37.0' IN ct.effectiveekus\nOR SIZE(ct.effectiveekus) = 0\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Tier Zero accounts not members of Denied RODC Password Replication Group", - "guid": "e9613406-e346-410b-a033-690a6cf0c708", + "name": "Domains affected by Exchange privilege escalation risk", + "guid": "f2d09c94-b6f2-4901-9a2d-f8bacd61edc7", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND (n:User or n:Computer)\nWITH n\nOPTIONAL MATCH (n)-[:MemberOf*1..]->(m:Group)\nWHERE m.objectid ENDS WITH '-519'\nWITH n, m\nWHERE m IS NULL\nRETURN n", + "query": "MATCH p=(n:Group)-[r:WriteDacl|ForceChangePassword|AddMember]->(m:Base)\nWHERE n.name STARTS WITH \"EXCHANGE \"\nAND ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -331,31 +385,61 @@ ] }, { - "name": "Collection health of specific computer", - "guid": "bb95c9c5-984c-4057-a430-000d684c069a", + "name": "Circular AD group memberships", + "guid": "fcaa5ffc-3d22-481f-a2a2-18a4eec30058", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "Returns Local groups and their members, and Principals with privileges", - "query": "MATCH p=(m:Base)-[:RemoteInteractiveLogonRight|AdminTo|CanRDP|LocalToComputer|MemberOfLocalGroup]-(n:Base)\n\n// Insert computer FQDN\nWHERE m.name ENDS WITH \"HOSTNAME.DOMAIN.LOCAL\"\n\nRETURN p", + "category": "Active Directory Hygiene", + "description": "Detects circular group membership chains where groups are members of themselves through one or more intermediate groups. This causes an administrative complexity.", + "query": "MATCH p=(x:Group)-[:MemberOf*2..]->(y:Group)\nWHERE x.objectid=y.objectid\nRETURN p\nLIMIT 100", "revision": 1, - "resources": [], + "resources": [ + "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" + ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Tier Zero users with email", - "guid": "9654c0d4-f1e8-4393-a2d1-53a5554a9de8", + "name": "Map domain trusts", + "guid": "268d3d26-5bc2-4820-a6ed-09d20f3d5413", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Domain Information", + "description": null, + "query": "MATCH p = (:Domain)-[:SameForestTrust|CrossForestTrust]->(:Domain)\nRETURN p\nLIMIT 1000", + "revision": 1, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Enrollment rights on published certificate templates with no security extension", + "guid": "0677b70c-4e04-4e89-a6a2-f5764604a6a7", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Certificate Services", + "description": null, + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE ct.nosecurityextension = true\nRETURN p\nLIMIT 1000", + "revision": 1, + "resources": [], + "acknowledgements": [] + }, + { + "name": "All Schema Admins", + "guid": "76d8e61d-7a86-40ff-8a85-fd37f1e2563f", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Tier Zero accounts with email access have an increased attack surface.", - "query": "MATCH (n)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.email <> \"\"\nAND n.enabled = true\nAND NOT toUpper(n.email) ENDS WITH \".ONMICROSOFT.COM\"\nAND NOT (\n (toUpper(n.email) STARTS WITH \"HEALTHMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHDISCOVERYMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHDISCOVERY\"\n OR toUpper(n.email) STARTS WITH \"MSEXCHAPPROVAL\"\n OR toUpper(n.email) STARTS WITH \"FEDERATEDEMAIL\"\n OR toUpper(n.email) STARTS WITH \"SYSTEMMAILBOX\"\n OR toUpper(n.email) STARTS WITH \"MIGRATION.\")\n AND\n (n.name STARTS WITH \"SM_\"\n OR n.name STARTS WITH \"HEALTHMAILBOX\")\n)\nRETURN n", + "category": "Domain Information", + "description": null, + "query": "MATCH p=(n:Base)-[:MemberOf*1..]->(m:Group)\nWHERE (n:User OR n:Computer)\nAND m.objectid ENDS WITH \"-518\" // Schema Admins\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -363,57 +447,57 @@ ] }, { - "name": "Domain Admins logons to non-Domain Controllers", - "guid": "e2f3fd0a-1df2-4089-b0a4-272ad6e369a9", + "name": "All service principals with Microsoft Graph App Role assignments", + "guid": "74440269-eb41-476b-8dec-b4095569b029", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Dangerous Privileges", + "category": "Microsoft Graph", "description": null, - "query": "MATCH (s)-[:MemberOf*0..]->(g:Group)\nWHERE g.objectid ENDS WITH '-516'\nWITH COLLECT(s) AS exclude\nMATCH p = (c:Computer)-[:HasSession]->(:User)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectid ENDS WITH '-512' AND NOT c IN exclude\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(:AZServicePrincipal)-[:AZMGAppRoleAssignment_ReadWrite_All|AZMGApplication_ReadWrite_All|AZMGDirectory_ReadWrite_All|AZMGGroupMember_ReadWrite_All|AZMGGroup_ReadWrite_All|AZMGRoleManagement_ReadWrite_Directory|AZMGServicePrincipalEndpoint_ReadWrite_All]->(:AZServicePrincipal)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Domains with smart card accounts where smart account passwords do not expire", - "guid": "97e05e67-5961-4aba-a8e7-fe5f92334035", + "name": "Map OU structure", + "guid": "8f14084b-5065-43d8-865a-a6ac52da25d1", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Domain Information", "description": null, - "query": "MATCH (s:Domain)-[:Contains*1..]->(t:Base)\nWHERE s.expirepasswordsonsmartcardonlyaccounts = false\nAND t.enabled = true\nAND t.smartcardrequired = true\nRETURN s", + "query": "MATCH p = (:Domain)-[:Contains*1..]->(:OU)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Enabled Tier Zero / High Value principals inactive for 60 days", - "guid": "72550bcb-3c4f-463d-8973-91a49163dc5a", + "name": "Enrollment rights on CertTemplates with OIDGroupLink", + "guid": "140a68eb-d21c-4b75-971f-309225fb2d75", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Active Directory Certificate Services", "description": null, - "query": "WITH 60 as inactive_days\nMATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nAND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO\nRETURN n", + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:ExtendedByPolicy]->(:IssuancePolicy)-[:OIDGroupLink]->(:Group)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Enabled computers inactive for 180 days", - "guid": "0768e810-1e1e-4319-a216-76d9c2058644", + "name": "Unresolved SID with outbound control", + "guid": "4e8429f9-cba2-41e9-bac6-0c42f96b2c57", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "WITH 180 as inactive_days\nMATCH (n:Computer)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT\nAND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO\nRETURN n\nLIMIT 1000", + "query": "MATCH p=(n:Base)-[r]->(:Base)\nWHERE r.isacl\nAND n.name CONTAINS \"S-1-5-21-\" // Unresolved SID\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [ @@ -421,45 +505,45 @@ ] }, { - "name": "Users with logon scripts stored in a trusted domain", - "guid": "8d94d3f3-3d53-4939-a206-3c0a4dd3f646", + "name": "Collection health of specific computer", + "guid": "bb95c9c5-984c-4057-a430-000d684c069a", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": null, - "query": "MATCH (n:User)\nWHERE n.logonscript IS NOT NULL\nMATCH (d:Domain)<-[:SameForestTrust|CrossForestTrust]-(:Domain)-[:Contains*1..]->(n)\nWITH n,last(split(d.name, '@')) AS domain\nWHERE toUpper(n.logonscript) STARTS WITH (\"\\\\\\\\\" + domain + \"\\\\\")\nRETURN n", - "revision": 2, + "category": "Domain Information", + "description": "Returns Local groups and their members, and Principals with privileges", + "query": "MATCH p=(m:Base)-[:RemoteInteractiveLogonRight|AdminTo|CanRDP|LocalToComputer|MemberOfLocalGroup]-(n:Base)\n\n// Insert computer FQDN\nWHERE m.name ENDS WITH \"HOSTNAME.DOMAIN.LOCAL\"\n\nRETURN p", + "revision": 1, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Workstations where Domain Users can RDP", - "guid": "9486e0e6-2617-4595-b969-cf57ca21fc86", + "name": "Principals with foreign domain group membership", + "guid": "8fb3214a-5a75-4ecd-b293-c121abd94b4b", "prebuilt": true, "platforms": [ "Active Directory" ], "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(s:Group)-[:CanRDP]->(t:Computer)\nWHERE s.objectid ENDS WITH '-513' AND NOT toUpper(t.operatingsystem) CONTAINS 'SERVER'\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(s:Base)-[:MemberOf]->(t:Group)\nWHERE s.domainsid<>t.domainsid\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Computers with non-default Primary Group membership", - "guid": "5862dc4e-6f6f-4321-9474-d838968495ed", + "name": "Tier Zero computers at risk of constrained delegation", + "guid": "8641e593-f2f2-48ba-bd45-fbc86e9f632a", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Computer)-[r:MemberOf]->(g:Group)\nWHERE NOT g.objectid ENDS WITH \"-515\" // Domain Computers\nAND NOT g.objectid ENDS WITH \"-516\" // Domain Controllers\nAND NOT g.objectid ENDS WITH \"-521\" // Read-Only Domain Controllers\nAND r.isprimarygroup = true\nRETURN p", + "query": "MATCH p = (n:Computer)<-[:AllowedToDelegate]-(:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -467,145 +551,152 @@ ] }, { - "name": "Domains with a minimum default password policy length less than 15 characters", - "guid": "7d258d2d-a43d-4a90-85d7-71c946ae5fd7", + "name": "Domains with a single-point-of-failure Domain Controller", + "guid": "3359a295-7cfd-491f-976b-c5a68647431c", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Domain)\nWHERE n.minpwdlength < 15\nRETURN n", + "query": "MATCH (n:Group)<-[:MemberOf]-(:Computer)\nWHERE n.objectid ENDS WITH '-516'\nWITH n, COUNT(n) AS dcCount\nWHERE dcCount = 1\nRETURN n", "revision": 1, - "resources": [ - "https://pages.nist.gov/800-63-3/sp800-63b.html" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Domain migration groups", - "guid": "f39c4953-ae92-4d67-bb50-eb1a161d4d3f", - "prebuilt": false, + "name": "Shortest paths from Owned objects to Tier Zero", + "guid": "dfaa8e8f-2c79-4e92-a291-b1347f6e83b0", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Shortest Paths", "description": null, - "query": "MATCH (n:Group)\nWHERE n.name CONTAINS \"$$$@\"\nRETURN n", + "query": "// MANY TO MANY SHORTEST PATH QUERIES USE EXCESSIVE SYSTEM RESOURCES AND TYPICALLY WILL NOT COMPLETE\nMATCH p=shortestPath((s:Tag_Owned)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "revision": 2, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Shortest paths from Domain Users to Tier Zero / High Value targets", + "guid": "469dc0f3-71b8-41b0-a03b-b4af7874665d", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Shortest Paths", + "description": null, + "query": "MATCH p=shortestPath((s:Group)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s.objectid ENDS WITH '-513' AND s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "revision": 2, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Principals with DES-only Kerberos authentication", + "guid": "d03ea1ef-70f0-439b-b1ef-d7f94ceb2af3", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Hygiene", + "description": null, + "query": "MATCH (n:Base)\nWHERE n.enabled = true\nAND n.usedeskeyonly = true\nRETURN n", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "PKI hierarchy", - "guid": "928acc23-ee4c-40a5-bde7-64c05cc1491d", + "name": "Domain controllers with weak certificate binding enabled", + "guid": "a2444d99-10b5-412d-8fea-4b063cfddd2c", "prebuilt": true, "platforms": [ "Active Directory" ], "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p=()-[:HostsCAService|IssuedSignedBy|EnterpriseCAFor|RootCAFor|TrustedForNTAuth|NTAuthStoreFor*..]->(:Domain)\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (s:Computer)-[:DCFor]->(:Domain)\nWHERE s.strongcertificatebindingenforcementraw = 0 OR s.strongcertificatebindingenforcementraw = 1\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Kerberos-enabled service accounts without AES encryption support", - "guid": "cb8cf96e-21c9-422b-9439-390a13446ca6", + "name": "Computer owners who can obtain LAPS passwords", + "guid": "92aa81d6-b08e-4abb-ae39-ecbe5735a74c", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Accounts without Kerberos AES encryption support, or passwords set before the existence of Windows Server 2008 Domain Controller which therefore lack AES encryption keys.", - "query": "MATCH (n:Base)\nWHERE n.hasspn = true\nAND ((\n n.supportedencryptiontypes <> ['Not defined']\n OR n.supportedencryptiontypes <> []\n OR NONE(type IN n.supportedencryptiontypes WHERE type CONTAINS 'AES128' OR type CONTAINS 'AES256')\n)\nOR (n.pwdlastset < 1204070400 // Password Last Set before Windows Server 2008\nAND NOT n.pwdlastset IN [-1.0, 0.0]\n))\nRETURN n\nLIMIT 100", - "revision": 2, + "category": "Dangerous Privileges", + "description": "Creators of computer objects get abusable rights on the computer object. If the owner is not explicitly granted ReadLAPSPassword they can still compromise the computer with the abusable owner rights.", + "query": "MATCH p = (c:Computer)<-[:GenericAll|Owns|WriteDacl|WriteOwner|AllExtendedRights]-(n:User)\nWHERE c.haslaps = true AND c.ownersid = n.objectid\nRETURN p", + "revision": 1, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Domains allowing unauthenticated domain enumeration", - "guid": "41a08d76-f8a5-4296-ad19-464c4c5c69fe", - "prebuilt": false, + "name": "Potential GPO 'Apply' misconfiguration", + "guid": "f5f2455e-afdc-4708-9a34-98f539ce52d8", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": null, - "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE (n.objectid ENDS WITH \"S-1-5-7\" // Anonymous\nOR n.objectid ENDS WITH \"S-1-1-0\") // Everyone\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", - "revision": 1, + "category": "Dangerous Privileges", + "description": "In Active Directory, GPO's are applied to objects in the Group Policy Management Console by ticking \"Allow - Apply group policy\", but administrators can mistakenly tick \"Allow - Write\" or \"Allow - Full Control\" resulting in a misconfigured GPO that allows a principal to compromise other principals the GPO also applies to. Results are potential risks and must be audited for for correctness.", + "query": "MATCH p=(n:Base)-[:GenericAll|GenericWrite]->(g:GPO)\n\n// Exclude Enterprise Admins and Domain Admins\nWHERE NOT n.objectid =~ \"-(519|512)$\"\n\n// Exclude unresolved SIDs\nAND NOT (n.distinguishedname IS NULL)\n\n// Asset description may reveal if it's a delegation group (false-positive) or a filter group (true-positive)\n//AND n.description is not null\n//AND n.description =~ \"(?i)apply\"\n\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Collection health of CA Registry Data", - "guid": "c8dd3479-8063-450a-9456-557bc5f39e10", + "name": "Domains with List Object mode enabled", + "guid": "05e2a94b-5ee6-47ec-b715-3982f30af01b", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Domain Information", - "description": "BloodHound's ADCS analysis requires collecting CA registry data to increase accuracy/enable more edges. Collection by default requires SharpHound has Administrators membership. Requires SharpHound v2.3.5 or above. It only requires one misconfigured CA to potentially a full forest compromise by any principal. CAs returned by this query have not been collected.", - "query": "MATCH p=(eca:EnterpriseCA)<-[:HostsCAService]-(c:Computer)\nWHERE (\n eca.isuserspecifiessanenabledcollected = false\n OR eca.casecuritycollected = false\n OR eca.enrollmentagentrestrictionscollected = false\n OR eca.roleseparationenabledcollected = false\n)\n// Exclude inactive CAs\nAND c.enabled = true\nAND c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400))\nRETURN p", + "description": "Checks the fDoListObject flag of dSHeuristics.", + "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{2}[^0].*\"\nRETURN n", "revision": 1, "resources": [ - "https://bloodhound.specterops.io/collect-data/enterprise-collection/permissions#ca-registry" + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Enabled computers inactive for 180 days - MSSQL Failover Cluster", - "guid": "d263e621-7f1b-4efb-ad25-098fc7d4fb72", - "prebuilt": false, - "platforms": [ - "Active Directory" - ], - "category": "Active Directory Hygiene", - "description": null, - "query": "WITH 180 as inactive_days\nMATCH (n:Computer)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND ANY(type IN n.serviceprincipalnames WHERE \n toLower(type) CONTAINS 'mssqlservercluster' OR \n toLower(type) CONTAINS 'mssqlserverclustermgmtapi' OR \n toLower(type) CONTAINS 'msclustervirtualserver')\nRETURN n\nLIMIT 1000", - "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/troubleshoot/windows-server/high-availability/troubleshoot-issues-accounts-used-failover-clusters#troubleshoot-password-issues-with-the-cluster-name-account" - ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] - }, - { - "name": "Principals with passwords stored using reversible encryption", - "guid": "ab900835-b2b8-4674-87b4-8b5141e80439", + "name": "On-Prem Users synced to Entra Users with Entra Admin Roles (direct)", + "guid": "de717635-d31f-4fbd-930b-b4dac0f22118", "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Active Directory Hygiene", + "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH (n:Base)\nWHERE n.encryptedtextpwdallowed = true\nRETURN n", + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZHasRole]->(:AZRole)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Tier Zero users not member of Protected Users", - "guid": "543eb01d-9fa3-4b8f-a936-b46bbfdaa2ae", + "name": "Enabled built-in guest user accounts", + "guid": "bb0f620d-6a55-4413-ac74-4c82905e8598", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (m:User)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nOPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base)\nWHERE g.objectid ENDS WITH '-525'\nWITH m, COLLECT(n) AS matchingNs\nWHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid)\nRETURN m", + "query": "MATCH (n:User)\nWHERE n.objectid ENDS WITH \"-501\"\nAND n.enabled = true\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [ @@ -613,91 +704,105 @@ ] }, { - "name": "Microsoft Entra Connect accounts with passwords not rotated in over 90 days", - "guid": "97fb1310-d15d-4d63-82a2-8788056250f1", + "name": "Large default groups with outbound control of OUs", + "guid": "310b3626-f8e6-4ab0-832c-72df6048597f", "prebuilt": false, "platforms": [ - "Active Directory", - "Azure" + "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Micosoft recommends to change the password of MSOL accounts every 90 days to prevent attackers from allowing use of the high privileges", - "query": "WITH 90 as days_since_change\nMATCH (u:User)\nWHERE u.name STARTS WITH \"MSOL_\"\nAND u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u", + "category": "Dangerous Privileges", + "description": null, + "query": "MATCH p=(n:Group)-[]->(:OU)\nWHERE n.objectid ENDS WITH \"-513\" // DOMAIN USERS\nOR n.objectid ENDS WITH \"-515\" // DOMAIN COMPUTERS\nOR n.objectid ENDS WITH \"-S-1-5-11\" // AUTHENTICATED USERS\nOR n.objectid ENDS WITH \"-S-1-1-0\" // EVERYONE\nOR n.objectid ENDS WITH \"S-1-5-32-545\" // USERS\nOR n.objectid ENDS WITH \"S-1-5-32-546\" // GUESTS\nOR n.objectid ENDS WITH \"S-1-5-7\" // ANONYMOUS\nRETURN p", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/defender-for-identity/rotate-password-microsoft-entra-connect" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Map OU structure", - "guid": "8f14084b-5065-43d8-865a-a6ac52da25d1", + "name": "Enrollment rights on published ESC1 certificate templates", + "guid": "2af855bc-f48f-4b22-9839-627d8231e425", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p = (:Domain)-[:Contains*1..]->(:OU)\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE ct.enrolleesuppliessubject = True\nAND ct.authenticationenabled = True\nAND ct.requiresmanagerapproval = False\nAND (ct.authorizedsignatures = 0 OR ct.schemaversion = 1)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "On-Prem Users synced to Entra Users that Own Entra Objects", - "guid": "4baf1026-e64c-4e31-afeb-2090b8090130", + "name": "Users which do not require password to authenticate", + "guid": "23bdc2ad-6739-4b2b-85d3-258e3f424eb2", "prebuilt": true, "platforms": [ - "Active Directory", - "Azure" + "Active Directory" ], - "category": "Cross Platform Attack Paths", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwns]->(:AZBase)\nRETURN p\nLIMIT 1000", + "query": "MATCH (u:User)\nWHERE u.passwordnotreqd = true\nRETURN u\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Computers with the outgoing NTLM setting set to Deny all", - "guid": "a9ddca74-feeb-4dbf-8b0f-de08b3cfa8a6", + "name": "Domain Admins logons to non-Domain Controllers", + "guid": "e2f3fd0a-1df2-4089-b0a4-272ad6e369a9", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "NTLM Relay Attacks", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (c:Computer)\nWHERE c.restrictoutboundntlm = True\nRETURN c LIMIT 1000", + "query": "MATCH (s)-[:MemberOf*0..]->(g:Group)\nWHERE g.objectid ENDS WITH '-516'\nWITH COLLECT(s) AS exclude\nMATCH p = (c:Computer)-[:HasSession]->(:User)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectid ENDS WITH '-512' AND NOT c IN exclude\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Disabled Tier Zero / High Value principals", - "guid": "d65a801f-d3ef-4b7e-8030-99ebfd6dad12", - "prebuilt": true, + "name": "Kerberos-enabled service accounts without AES encryption support", + "guid": "cb8cf96e-21c9-422b-9439-390a13446ca6", + "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": null, - "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = false\nAND NOT n.objectid ENDS WITH '-502' // Removes false positive, KRBTGT\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nRETURN n\nLIMIT 100", + "description": "Accounts without Kerberos AES encryption support, or passwords set before the existence of Windows Server 2008 Domain Controller which therefore lack AES encryption keys.", + "query": "MATCH (n:Base)\nWHERE n.hasspn = true\nAND ((\n n.supportedencryptiontypes <> ['Not defined']\n OR n.supportedencryptiontypes <> []\n OR NONE(type IN n.supportedencryptiontypes WHERE type CONTAINS 'AES128' OR type CONTAINS 'AES256')\n)\nOR (n.pwdlastset < 1204070400 // Password Last Set before Windows Server 2008\nAND NOT n.pwdlastset IN [-1.0, 0.0]\n))\nRETURN n\nLIMIT 100", + "revision": 2, + "resources": [], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] + }, + { + "name": "ACEs across trusts", + "guid": "c902d3b4-1a75-4335-acd7-28246dab746d", + "prebuilt": false, + "platforms": [ + "Active Directory" + ], + "category": "Domain Information", + "description": "ACEs granted across a trust, the ACEs are set on trusting objects and the rights are granted to objects from trusted domains.", + "query": "MATCH p=(trustedDomainPrincipal:Base)-[r]->(trustingDomainPrincipal:Base)\nWHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid\nAND r.isacl\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Domains affected by AdPrep privilege escalation risk", - "guid": "815ff190-f6f3-4757-a516-2f4bf589b705", + "name": "Usage of built-in domain Administrator account", + "guid": "35b1206f-871b-44aa-a601-c5258060dfcf", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", - "description": null, - "query": "MATCH p=(n:Group)-[r:GenericAll]->(m:Domain)\nWHERE n.objectid ENDS WITH \"-527\" // Enterprise Key Admins\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "category": "Active Directory Hygiene", + "description": "Usage of Active Directory's built-in Administrator account is a sign that the account is not only used for break-glass purposes.", + "query": "MATCH (n:User)\nWHERE n.objectid ENDS WITH \"-500\"\nAND (\n n.lastlogontimestamp > (datetime().epochseconds - (60 * 86400)) OR\n n.lastlogon > (datetime().epochseconds - (60 * 86400))\n)\nAND NOT n.whencreated > (datetime().epochseconds - (60 * 86400))\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [ @@ -705,65 +810,61 @@ ] }, { - "name": "Computers with unsupported operating systems", - "guid": "d06d3b14-0318-4fa9-9639-4b79ccaf3c2c", + "name": "Computers with membership in Protected Users", + "guid": "a26372f4-2e92-49f6-8993-6657fbc1569a", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH (c:Computer)\nWHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*'\nRETURN c\nLIMIT 100", + "query": "MATCH p = (:Base)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectid ENDS WITH \"-525\"\nRETURN p LIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "AS-REP Roastable Tier Zero users (DontReqPreAuth)", - "guid": "6d51e4dc-e1ad-477a-b6c6-324f18f03120", + "name": "Non-default members in Pre-Windows 2000 Compatible Access", + "guid": "091995b9-7254-473a-996f-6b8368d20431", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.dontreqpreauth = true\nRETURN n", + "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE NOT n.objectid ENDS WITH \"S-1-5-11\" // Authenticated Users\nAND NOT (n.objectid ENDS WITH \"S-1-5-7\" // Anonymous\nAND NOT n.objectid ENDS WITH \"S-1-1-0\") // Everyone\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", "revision": 1, - "resources": [ - "https://attack.mitre.org/techniques/T1558/004/" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Foreign Service Principals With any Abusable MS Graph App Role Assignment", - "guid": "d7a180c8-5624-4fc1-a407-deeb2ad3054c", + "name": "Domain migration groups", + "guid": "f39c4953-ae92-4d67-bb50-eb1a161d4d3f", "prebuilt": false, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Dangerous Privileges", - "description": "MS Graph app role assignments provide significant power within an Entra ID tenant, similar to an Admin role.", - "query": "MATCH p = (sp1:AZServicePrincipal)-[r:AZMGGroupMember_ReadWrite_All|AZMGServicePrincipalEndpoint_ReadWrite_All|AZMGAppRoleAssignment_ReadWrite_All|AZMGGroup_ReadWrite_All|AZMGDirectory_ReadWrite_All|AZMGRoleManagement_ReadWrite_Directory]->(sp2:AZServicePrincipal)\nWHERE toUpper(sp1.appownerorganizationid) <> toUpper(sp1.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp1.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", + "category": "Domain Information", + "description": null, + "query": "MATCH (n:Group)\nWHERE n.name CONTAINS \"$$$@\"\nRETURN n", "revision": 1, - "resources": [ - "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" - ], + "resources": [], "acknowledgements": [ - "Stephen Hinck" + "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Computer owners who can obtain LAPS passwords", - "guid": "92aa81d6-b08e-4abb-ae39-ecbe5735a74c", + "name": "Non-default delegation on MicrosoftDNS container", + "guid": "008792c0-4458-46a1-a10d-50cdaf95af1e", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", - "description": "Creators of computer objects get abusable rights on the computer object. If the owner is not explicitly granted ReadLAPSPassword they can still compromise the computer with the abusable owner rights.", - "query": "MATCH p = (c:Computer)<-[:GenericAll|Owns|WriteDacl|WriteOwner|AllExtendedRights]-(n:User)\nWHERE c.haslaps = true AND c.ownersid = n.objectid\nRETURN p", + "category": "Active Directory Hygiene", + "description": null, + "query": "MATCH p=(n:Base)-[r]->(m:Container)\nWHERE m.distinguishedname STARTS WITH \"CN=MICROSOFTDNS,CN=SYSTEM,DC=\"\nAND NOT n.name STARTS WITH \"DNSADMINS@\"\nAND NOT n.objectid =~ \"-(512|544|519|9)$\"\nAND r.isacl\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -771,29 +872,50 @@ ] }, { - "name": "Foreign principals in Tier Zero / High Value targets", - "guid": "95bec736-86ef-4017-8465-9b9b66548b17", + "name": "Non-Tier Zero account with 'Admin Count' flag", + "guid": "e7f703b3-5dba-4aef-8346-4d589be2c828", + "prebuilt": false, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Hygiene", + "description": "Users who were a member of one of AD's built-in administrative groups but are not currently Tier Zero.", + "query": "MATCH (n:User)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.admincount = true\nRETURN n", + "revision": 1, + "resources": [ + "https://learn.microsoft.com/en-us/windows/win32/adschema/a-admincount" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] + }, + { + "name": "Domains where any user can join a computer to the domain", + "guid": "421921fa-bc0f-4659-9680-b7481adcb132", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Azure Hygiene", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:AZServicePrincipal)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT toUpper(n.appownerorganizationid) = toUpper(n.tenantid)\nAND n.appownerorganizationid CONTAINS '-'\nRETURN n\nLIMIT 100", + "query": "MATCH (n:Domain)\nWHERE n.machineaccountquota > 0\nRETURN n", "revision": 1, - "resources": [], + "resources": [ + "https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/default-workstation-numbers-join-domain", + "https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/add-workstations-to-domain" + ], "acknowledgements": [] }, { - "name": "Enabled users inactive for 180 days", - "guid": "71972f3c-b32d-4023-a841-5cc8cc1c1867", + "name": "Tier Zero accounts that can be delegated", + "guid": "4316eaf1-6af0-4879-8f55-ac2633a711c3", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Kerberos Interaction", "description": null, - "query": "WITH 180 as inactive_days\nMATCH (n:User)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nRETURN n\nLIMIT 1000", + "query": "MATCH (m:Base)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nAND m.enabled = true\nAND m.sensitive = false\nOPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base)\nWHERE g.objectid ENDS WITH '-525'\nWITH m, COLLECT(n) AS matchingNs\nWHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid)\nRETURN m", "revision": 1, "resources": [], "acknowledgements": [ @@ -801,422 +923,425 @@ ] }, { - "name": "Non-default permissions on IssuancePolicy nodes", - "guid": "b2280665-c91b-448c-8c0f-97d1f38b6f59", - "prebuilt": true, + "name": "Members of Allowed RODC Password Replication Group", + "guid": "19fc5acd-e30a-4038-a5b5-2e0494f93373", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "Domain Information", "description": null, - "query": "MATCH p = (s:Base)-[:GenericAll|GenericWrite|Owns|WriteOwner|WriteDacl]->(:IssuancePolicy)\nWHERE NOT s.objectid ENDS WITH '-512' AND NOT s.objectid ENDS WITH '-519'\nRETURN p\nLIMIT 1000", - "revision": 1, + "query": "MATCH p=(:Base)-[:MemberOf*1..]->(m:Group)\nWHERE m.objectid ENDS WITH \"-571\"\nRETURN p", + "revision": 2, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "All service principals with Microsoft Graph App Role assignments", - "guid": "74440269-eb41-476b-8dec-b4095569b029", - "prebuilt": true, + "name": "Map Azure Management structure", + "guid": "c1bb109e-e6a4-4c91-864f-f78e1e42615e", + "prebuilt": false, "platforms": [ "Azure" ], - "category": "Microsoft Graph", - "description": null, - "query": "MATCH p=(:AZServicePrincipal)-[:AZMGAppRoleAssignment_ReadWrite_All|AZMGApplication_ReadWrite_All|AZMGDirectory_ReadWrite_All|AZMGGroupMember_ReadWrite_All|AZMGGroup_ReadWrite_All|AZMGRoleManagement_ReadWrite_Directory|AZMGServicePrincipalEndpoint_ReadWrite_All]->(:AZServicePrincipal)\nRETURN p\nLIMIT 1000", + "category": "Kerberos Interaction", + "description": "Maps the structure of Azure Management", + "query": "MATCH p = (:AZTenant)-[:AZContains*1..]->(:AZResourceGroup)\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [], - "acknowledgements": [] + "resources": [ + "https://learn.microsoft.com/en-us/azure/governance/management-groups/overview" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Map domain trusts", - "guid": "268d3d26-5bc2-4820-a6ed-09d20f3d5413", + "name": "On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated)", + "guid": "609d648f-7fb8-42d3-ad99-626f9ce1f121", "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Domain Information", + "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH p = (:Domain)-[:SameForestTrust|CrossForestTrust]->(:Domain)\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZHasRole]->(:AZRole)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Locations of Tier Zero / High Value objects", - "guid": "18a83a17-b451-4343-acfe-7620516e2968", + "name": "Tier Zero AD principals synchronized with Entra ID", + "guid": "a8b6ec67-21aa-4dd2-8906-47bb81bf5262", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Domain Information", + "category": "Azure Hygiene", "description": null, - "query": "MATCH p = (t:Base)<-[:Contains*1..]-(:Domain)\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "query": "MATCH (ENTRA:AZBase)\nMATCH (AD:Base)\nWHERE ((AD:Tag_Tier_Zero) OR COALESCE(AD.system_tags, '') CONTAINS 'admin_tier_0')\nAND ENTRA.onpremsyncenabled = true\nAND ENTRA.onpremid = AD.objectid\nRETURN ENTRA\n// Replace 'RETURN ENTRA' with 'RETURN AD' to see the corresponding AD principals\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Trace ACE inheritance", - "guid": "8c5454df-3ae8-412c-b271-3c4c55df7141", - "prebuilt": false, + "name": "Paths from Domain Users to Tier Zero / High Value targets", + "guid": "977bec40-565c-40b8-90c8-e3e122c291cd", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "When BloodHound shows that an inherited ACE applies to an object it does not show the source/where it is inherited from from (OU, Container, Domain root) - the source is where it should be remediated. This query can sometimes find the source of an inherited ACE, but only works if the ACE is set to also apply to the source itself.", - "query": "// Replace INSERT_OBJECT_ID with the affected principal\n// Replace 'GenericAll' with the specific edge you're tracing\nWITH \"INSERT_OBJECT_ID\" as OID\nMATCH p=()-[:GenericAll {isacl:true,isinherited:false}]->()-[:Contains*1..]->(:Base{objectid:OID})\nWHERE NONE(ou in NODES(p) WHERE ou:OU AND ou.isaclprotected IS NOT NULL)\nRETURN p", - "revision": 1, + "category": "Dangerous Privileges", + "description": null, + "query": "MATCH p=shortestPath((s:Group)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s.objectid ENDS WITH '-513' AND s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], - "acknowledgements": [ - "Walter.Legowski, @SadProcessor" - ] + "acknowledgements": [] }, { - "name": "Domains with a single-point-of-failure Domain Controller", - "guid": "3359a295-7cfd-491f-976b-c5a68647431c", - "prebuilt": false, + "name": "Kerberoastable users with most admin privileges", + "guid": "9907b208-494c-4ba6-846d-485e6de14e17", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Kerberos Interaction", "description": null, - "query": "MATCH (n:Group)<-[:MemberOf]-(:Computer)\nWHERE n.objectid ENDS WITH '-516'\nWITH n, COUNT(n) AS dcCount\nWHERE dcCount = 1\nRETURN n", + "query": "MATCH (u:User)\nWHERE u.hasspn = true\n AND u.enabled = true\n AND NOT u.objectid ENDS WITH '-502'\n AND NOT COALESCE(u.gmsa, false) = true\n AND NOT COALESCE(u.msa, false) = true\nMATCH (u)-[:MemberOf|AdminTo*1..]->(c:Computer)\nWITH DISTINCT u, COUNT(c) AS adminCount\nRETURN u\nORDER BY adminCount DESC\nLIMIT 100", "revision": 1, - "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "resources": [ + "https://attack.mitre.org/techniques/T1558/003/" + ], + "acknowledgements": [] }, { - "name": "Domains exempting privileged groups from AdminSDHolder protections", - "guid": "79f8d8f9-8291-4bf7-a13a-15989018075f", + "name": "AdminSDHolder protected Accounts and Groups", + "guid": "5ee2f40e-a55c-4140-ab8a-91746ba3752b", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Checks the dwAdminSDExMask flag of dSHeuristics.", - "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{15}[^0].*\"\nRETURN n", + "category": "Domain Information", + "description": "Objects whose permissions are set by SDProp to the template AdminSDHolder object as per MS-ADTS 3.1.1.6.1.2 Protected Objects. Does not exclude objects if specified in dSHeuristics dwAdminSDExMask", + "query": "MATCH (n:Base)-[:MemberOf*0..]->(m:Group)\nWHERE (\n n.objectid =~ \".*-(S-1-5-32-544|S-1-5-32-548|S-1-5-32-549|S-1-5-32-550|S-1-5-32-551|S-1-5-32-552|518|512|519)$\" // Groups\n OR m.objectid =~ \".*-(S-1-5-32-544|S-1-5-32-548|S-1-5-32-549|S-1-5-32-550|S-1-5-32-551|S-1-5-32-552|518|512|519)$\" // Members of groups\n OR n.objectid =~ \".*-(500|502|516|521)$\" // Direct objects\n)\nRETURN n", "revision": 1, "resources": [ - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/a0d0b4fa-2895-4c64-b182-ba64ad0f84b8", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Domains affected by Exchange privilege escalation risk", - "guid": "f2d09c94-b6f2-4901-9a2d-f8bacd61edc7", - "prebuilt": false, + "name": "Nested groups within Tier Zero / High Value", + "guid": "8e541e75-df1d-423f-b429-4bbf0403a338", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Group)-[r:WriteDacl|ForceChangePassword|AddMember]->(m:Base)\nWHERE n.name STARTS WITH \"EXCHANGE \"\nAND ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "query": "MATCH p=(t:Group)<-[:MemberOf*..]-(s:Group)\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT s.objectid ENDS WITH '-512' // Domain Admins\nAND NOT s.objectid ENDS WITH '-519' // Enterprise Admins\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Tier Zero accounts that can be delegated", - "guid": "4316eaf1-6af0-4879-8f55-ac2633a711c3", - "prebuilt": false, + "name": "Principals with DCSync privileges", + "guid": "6e9beb8a-ad14-43de-bda1-644d174a5906", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Kerberos Interaction", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (m:Base)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nAND m.enabled = true\nAND m.sensitive = false\nOPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base)\nWHERE g.objectid ENDS WITH '-525'\nWITH m, COLLECT(n) AS matchingNs\nWHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid)\nRETURN m", + "query": "MATCH p=(:Base)-[:DCSync|AllExtendedRights|GenericAll]->(:Domain)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] - }, - { - "name": "Shortest paths from Azure Applications to Tier Zero / High Value targets", - "guid": "60ff7c58-a98e-4bc1-9e32-8378d2db0c43", - "prebuilt": true, - "platforms": [ - "Azure" - ], - "category": "Shortest Paths", - "description": null, - "query": "MATCH p=shortestPath((s:AZApp)-[:AZ_ATTACK_PATHS*1..]->(t:AZBase))\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') AND s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], "acknowledgements": [] }, { - "name": "All Kerberoastable users", - "guid": "14ab4eaa-b73b-49c4-b2d1-1e020757c995", - "prebuilt": true, + "name": "Collection health of DC Registry Data", + "guid": "3f0fa2f3-fbdf-42c0-9e7d-97e689009161", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Kerberos Interaction", - "description": null, - "query": "MATCH (u:User)\nWHERE u.hasspn=true\nAND u.enabled = true\nAND NOT u.objectid ENDS WITH '-502'\nAND NOT COALESCE(u.gmsa, false) = true\nAND NOT COALESCE(u.msa, false) = true\nRETURN u\nLIMIT 100", + "category": "Domain Information", + "description": "BloodHound's ADCS analysis requires collecting CA registry data to increase accuracy/enable more edges. Collection by default requires SharpHound has Administrators membership. Requires SharpHound v2.3.5 or above. It only requires one misconfigured DC to potentially a full forest compromise by any principal. DCs returned by this query have not been collected.", + "query": "MATCH p=(:Domain)<-[:DCFor]-(c:Computer)\nWHERE c.strongcertificatebindingenforcementraw IS NULL\n// Exclude inactive DCs\nAND c.enabled = true\nAND c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400))\nRETURN p", "revision": 1, "resources": [ - "https://attack.mitre.org/techniques/T1558/003/" + "https://bloodhound.specterops.io/collect-data/enterprise-collection/permissions#dc-registry" ], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Tier Zero AD principals synchronized with Entra ID", - "guid": "a8b6ec67-21aa-4dd2-8906-47bb81bf5262", - "prebuilt": true, + "name": "Microsoft Entra Connect accounts with passwords not rotated in over 90 days", + "guid": "97fb1310-d15d-4d63-82a2-8788056250f1", + "prebuilt": false, "platforms": [ + "Active Directory", "Azure" ], - "category": "Azure Hygiene", - "description": null, - "query": "MATCH (ENTRA:AZBase)\nMATCH (AD:Base)\nWHERE ((AD:Tag_Tier_Zero) OR COALESCE(AD.system_tags, '') CONTAINS 'admin_tier_0')\nAND ENTRA.onpremsyncenabled = true\nAND ENTRA.onpremid = AD.objectid\nRETURN ENTRA\n// Replace 'RETURN ENTRA' with 'RETURN AD' to see the corresponding AD principals\nLIMIT 100", + "category": "Active Directory Hygiene", + "description": "Micosoft recommends to change the password of MSOL accounts every 90 days to prevent attackers from allowing use of the high privileges", + "query": "WITH 90 as days_since_change\nMATCH (u:User)\nWHERE u.name STARTS WITH \"MSOL_\"\nAND u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u", "revision": 1, - "resources": [], - "acknowledgements": [] + "resources": [ + "https://learn.microsoft.com/en-us/defender-for-identity/rotate-password-microsoft-entra-connect" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Enrollment rights on published enrollment agent certificate templates", - "guid": "8483bf5b-89f1-4723-abb2-c48295f6393e", - "prebuilt": true, + "name": "Non-Tier Zero account with excessive control", + "guid": "944cecfe-519b-4318-b226-e8520161b454", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", - "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE '1.3.6.1.4.1.311.20.2.1' IN ct.effectiveekus\nOR '2.5.29.37.0' IN ct.effectiveekus\nOR SIZE(ct.effectiveekus) = 0\nRETURN p\nLIMIT 1000", - "revision": 1, + "category": "Dangerous Privileges", + "description": "Returns non-Tier Zero principals with >= 1000 direct rights to other principals. This does not include rights from group memberships.", + "query": "MATCH (n:Base)-[r:AD_ATTACK_PATHS]->(m:Base)\nWHERE NOT r:MemberOf\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nWITH n, COLLECT(DISTINCT(m)) AS endNodes\nWHERE SIZE(endNodes) >= 1000\nRETURN n", + "revision": 3, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "All Global Administrators", - "guid": "94d7d765-6837-4eb8-aa33-e1c9ef262cdc", - "prebuilt": true, + "name": "Computers with non-default Primary Group membership", + "guid": "5862dc4e-6f6f-4321-9474-d838968495ed", + "prebuilt": false, "platforms": [ - "Azure" + "Active Directory" ], - "category": "General", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p = (:AZBase)-[:AZGlobalAdmin*1..]->(:AZTenant)\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(n:Computer)-[r:MemberOf]->(g:Group)\nWHERE NOT g.objectid ENDS WITH \"-515\" // Domain Computers\nAND NOT g.objectid ENDS WITH \"-516\" // Domain Controllers\nAND NOT g.objectid ENDS WITH \"-521\" // Read-Only Domain Controllers\nAND r.isprimarygroup = true\nRETURN p", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Devices with unsupported operating systems", - "guid": "e3f2b53a-7ce6-4e52-9c74-68b69338288b", + "name": "Accounts with weak password storage encryption", + "guid": "8bd6fcf2-3f3c-414c-857a-4caf28e49def", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Azure Hygiene", - "description": null, - "query": "MATCH (n:AZDevice)\nWHERE n.operatingsystem CONTAINS 'WINDOWS'\nAND n.operatingsystemversion =~ '(10.0.19044|10.0.22000|10.0.19043|10.0.19042|10.0.19041|10.0.18363|10.0.18362|10.0.17763|10.0.17134|10.0.16299|10.0.15063|10.0.14393|10.0.10586|10.0.10240|6.3.9600|6.2.9200|6.1.7601|6.0.6200|5.1.2600|6.0.6003|5.2.3790|5.0.2195).?.*'\nRETURN n\nLIMIT 100", - "revision": 1, - "resources": [], - "acknowledgements": [] + "category": "Active Directory Hygiene", + "description": "Accounts with passwords set before the existence of Windows Server 2008 Domain Controller which therefore lack AES encryption keys.", + "query": "MATCH (n:Base)\nWHERE n.pwdlastset < 1204070400 // Password Last Set before Windows Server 2008 release\nRETURN n\nLIMIT 100", + "revision": 2, + "resources": [ + "https://techcommunity.microsoft.com/blog/coreinfrastructureandsecurityblog/decrypting-the-selection-of-supported-kerberos-encryption-types/1628797" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Enrollment rights on published certificate templates with no security extension", - "guid": "0677b70c-4e04-4e89-a6a2-f5764604a6a7", - "prebuilt": true, + "name": "Domains allowing unauthenticated rootDSE searches and binds", + "guid": "ebc79aa4-e816-4be8-93fe-a0b30dbc771d", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", - "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE ct.nosecurityextension = true\nRETURN p\nLIMIT 1000", + "category": "Active Directory Hygiene", + "description": "Checks the fLDAPBlockAnonOps flag of dSHeuristics.", + "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{6}[^2].*\"\nRETURN n", "revision": 1, - "resources": [], - "acknowledgements": [] + "resources": [ + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Enabled built-in guest user accounts", - "guid": "bb0f620d-6a55-4413-ac74-4c82905e8598", - "prebuilt": false, + "name": "DCs vulnerable to NTLM relay to LDAP attacks", + "guid": "3f87e0b0-fc06-4986-a94c-e08781253dc8", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH (n:User)\nWHERE n.objectid ENDS WITH \"-501\"\nAND n.enabled = true\nRETURN n", + "query": "MATCH p = (dc:Computer)-[:DCFor]->(:Domain)\nWHERE (dc.ldapavailable = True AND dc.ldapsigning = False)\nOR (dc.ldapsavailable = True AND dc.ldapsepa = False)\nOR (dc.ldapavailable = True AND dc.ldapsavailable = True AND dc.ldapsigning = False and dc.ldapsepa = True)\nRETURN p", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "KRBTGT accounts with passwords not rotated in over 1 year", - "guid": "1b3ae310-ffa7-4ce5-a37f-6111aef600c8", + "name": "All ADCS ESC privilege escalation edges", + "guid": "49db8edc-8421-438f-b97b-23c042959bef", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH (n:User)\nWHERE (n.objectid ENDS WITH '-502'\nOR n.name STARTS WITH 'AZUREADKERBEROS.'\nOR n.name STARTS WITH 'KRBTGT_AZUREAD@')\nAND n.pwdlastset < (datetime().epochseconds - (365 * 86400))\nRETURN n", + "query": "MATCH p=(:Base)-[:ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|GoldenCert|CoerceAndRelayNTLMToADCS]->(:Base)\nRETURN p", "revision": 1, - "resources": [], + "resources": [ + "https://posts.specterops.io/certified-pre-owned-d95910965cd2", + "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-1-799f3d3b03cf", + "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-2-ac7f925d1547", + "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-3-33efb00856ac", + "https://posts.specterops.io/adcs-esc13-abuse-technique-fda4272fbd53", + "https://specterops.io/blog/2025/04/08/the-renaissance-of-ntlm-relay-attacks-everything-you-need-to-know/#:~:text=Introducing%20the%20CoerceAndRelayNTLMToADCS%20Edge" + ], "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" + "Jonas B\u00fclow Knudsen, @Jonas_B_K" ] }, { - "name": "Computers not requiring inbound SMB signing", - "guid": "6b1fcfb6-b010-41a2-9d31-f9872fe994ff", + "name": "Principals with weak supported Kerberos encryption types", + "guid": "ca329573-2157-41da-ab17-4d122c54b11d", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "NTLM Relay Attacks", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Computer)\nWHERE n.smbsigning = False\nRETURN n", + "query": "MATCH (u:Base)\nWHERE 'DES-CBC-CRC' IN u.supportedencryptiontypes\nOR 'DES-CBC-MD5' IN u.supportedencryptiontypes\nOR 'RC4-HMAC-MD5' IN u.supportedencryptiontypes\nRETURN u", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Tier Zero computers at risk of resource-based constrained delegation", - "guid": "4dc97cf4-3c03-4fe6-8a8b-4f665c67e1e5", + "name": "Object name conflict", + "guid": "c561c4f8-ea45-453f-85a2-3fc2e20e7f8c", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", - "description": null, - "query": "MATCH p = (n:Computer)<-[:AllowedToAct]-(:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "category": "Active Directory Hygiene", + "description": "When two objects are created with the same Relative Distinguished Name (RDN) in the same parent Organizational Unit or container, the conflict is recognized by the system when one of the new objects replicates to another domain controller. When this happens, one of the objects is renamed with 'CNF'", + "query": "MATCH (n:Base)\nWHERE n.distinguishedname CONTAINS 'CNF:'\nRETURN n", "revision": 1, - "resources": [], + "resources": [ + "https://learn.microsoft.com/en-us/archive/technet-wiki/15435.active-directory-duplicate-object-name-resolution" + ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Enrollment rights on published ESC2 certificate templates", - "guid": "ebc77984-1ceb-4ed2-a395-ce1067847941", + "name": "Domain controllers with UPN certificate mapping enabled", + "guid": "799ea3ce-572b-4594-98c4-041aa2ae6176", "prebuilt": true, "platforms": [ "Active Directory" ], "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(c:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE c.requiresmanagerapproval = false\nAND (c.effectiveekus = [''] OR '2.5.29.37.0' IN c.effectiveekus OR c.effectiveekus IS NULL)\nAND (c.authorizedsignatures = 0 OR c.schemaversion = 1)\nRETURN p\nLIMIT 1000", - "revision": 2, + "query": "MATCH p = (s:Computer)-[:DCFor]->(:Domain)\nWHERE s.certificatemappingmethodsraw IN [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]\nRETURN p\nLIMIT 1000", + "revision": 1, "resources": [ - "https://posts.specterops.io/certified-pre-owned-d95910965cd2", - "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-2-ac7f925d1547" + "https://support.microsoft.com/en-us/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16", + "https://specterops.io/blog/2024/02/28/adcs-esc14-abuse-technique/" ], - "acknowledgements": [] + "acknowledgements": [ + "Jonas B\u00fclow Knudsen, @Jonas_B_K" + ] }, { - "name": "Users which do not require password to authenticate", - "guid": "23bdc2ad-6739-4b2b-85d3-258e3f424eb2", + "name": "Entra Users synced from On-Prem Users added to Domain Admins group", + "guid": "62722d5f-bd93-4d11-beeb-9be261827e4e", "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Active Directory Hygiene", + "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH (u:User)\nWHERE u.passwordnotreqd = true\nRETURN u\nLIMIT 100", + "query": "MATCH p = (:AZUser)-[:SyncedToADUser]->(:User)-[:MemberOf]->(t:Group)\nWHERE t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Large default groups with outbound control", - "guid": "a334f21a-3d7f-448e-b7ea-1465a3127bce", + "name": "Tier Zero computers with passwords older than the default maximum password age", + "guid": "b6d6d0bf-130e-4719-996b-adc29bba36e9", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Group)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC5|ADCSESC6a|ADCSESC6b|ADCSESC7|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13]->(:Base)\nWHERE n.objectid ENDS WITH \"-513\" // DOMAIN USERS\nOR n.objectid ENDS WITH \"-515\" // DOMAIN COMPUTERS\nOR n.objectid ENDS WITH \"-S-1-5-11\" // AUTHENTICATED USERS\nOR n.objectid ENDS WITH \"-S-1-1-0\" // EVERYONE\nOR n.objectid ENDS WITH \"S-1-5-32-545\" // USERS\nOR n.objectid ENDS WITH \"S-1-5-32-546\" // GUESTS\nOR n.objectid ENDS WITH \"S-1-5-7\" // ANONYMOUS\nRETURN p", - "revision": 1, + "query": "MATCH (n:Computer)\nWHERE n.enabled = true\nAND n.whencreated < (datetime().epochseconds - (60 * 3 * 86400))\nAND n.pwdlastset < (datetime().epochseconds - (60 * 3 * 86400))\nAND ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", + "revision": 2, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Shortest paths to Azure Subscriptions", - "guid": "4785b305-c101-461c-80fc-3fb3ff67a8ce", - "prebuilt": true, - "platforms": [ - "Azure" - ], - "category": "Shortest Paths", - "description": null, - "query": "MATCH p=shortestPath((s:AZBase)-[:AZ_ATTACK_PATHS*1..]->(t:AZSubscription))\nWHERE s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], - "acknowledgements": [] - }, - { - "name": "Disabled Tier Zero / High Value principals", - "guid": "860d5c2d-84fe-4c85-80de-e0a9badbd0e7", + "name": "PKI hierarchy", + "guid": "928acc23-ee4c-40a5-bde7-64c05cc1491d", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Azure Hygiene", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH (n:AZBase)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = false\nRETURN n\nLIMIT 100", + "query": "MATCH p=()-[:HostsCAService|IssuedSignedBy|EnterpriseCAFor|RootCAFor|TrustedForNTAuth|NTAuthStoreFor*..]->(:Domain)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "All service principals with Microsoft Graph privilege to grant arbitrary App Roles", - "guid": "e6d6b5da-89da-4514-a409-2d6e368397da", + "name": "Cross-forest trusts with abusable configuration", + "guid": "5cf1f354-80d4-420e-bc4b-424fabc21a56", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Microsoft Graph", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(:AZServicePrincipal)-[:AZMGGrantAppRoles]->(:AZTenant)\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(n:Domain)-[:CrossForestTrust|SpoofSIDHistory|AbuseTGTDelegation]-(m:Domain)\nWHERE (n)-[:SpoofSIDHistory|AbuseTGTDelegation]-(m)\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Accounts with weak password storage encryption", - "guid": "8bd6fcf2-3f3c-414c-857a-4caf28e49def", - "prebuilt": true, + "name": "Domains exempting privileged groups from AdminSDHolder protections", + "guid": "79f8d8f9-8291-4bf7-a13a-15989018075f", + "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "Accounts with passwords set before the existence of Windows Server 2008 Domain Controller which therefore lack AES encryption keys.", - "query": "MATCH (n:Base)\nWHERE n.pwdlastset < 1204070400 // Password Last Set before Windows Server 2008 release\nRETURN n\nLIMIT 100", - "revision": 2, + "description": "Checks the dwAdminSDExMask flag of dSHeuristics.", + "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{15}[^0].*\"\nRETURN n", + "revision": 1, "resources": [ - "https://techcommunity.microsoft.com/blog/coreinfrastructureandsecurityblog/decrypting-the-selection-of-supported-kerberos-encryption-types/1628797" + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Non-Tier Zero accounts with SID History of Tier Zero accounts", - "guid": "59744dfe-9411-4daf-b342-1203dc62acd4", + "name": "Tier Zero accounts not members of Denied RODC Password Replication Group", + "guid": "e9613406-e346-410b-a033-690a6cf0c708", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND (n:User or n:Computer)\nWITH n\nOPTIONAL MATCH (n)-[:MemberOf*1..]->(m:Group)\nWHERE m.objectid ENDS WITH '-519'\nWITH n, m\nWHERE m IS NULL\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [ @@ -1224,15 +1349,29 @@ ] }, { - "name": "Accounts with SID History to a non-existent domain", - "guid": "2710401a-c4c2-4d2c-9edb-d7625045f2e8", + "name": "Shortest paths to Domain Admins from Kerberoastable users", + "guid": "bd163361-1e05-47c7-908b-962aef251535", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Shortest Paths", + "description": null, + "query": "MATCH p=shortestPath((s:User)-[:AD_ATTACK_PATHS*1..]->(t:Group))\nWHERE s.hasspn=true\nAND s.enabled = true\nAND NOT s.objectid ENDS WITH '-502'\nAND NOT COALESCE(s.gmsa, false) = true\nAND NOT COALESCE(s.msa, false) = true\nAND t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", + "revision": 2, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Kerberos-enabled service account member of built-in Admins groups", + "guid": "42a856fc-257a-4142-9592-ca95fd49e579", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (d:Domain)\nWITH collect(d.objectid) AS domainSIDs\nMATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE NOT n.domainsid IN domainSIDs\nRETURN p", + "query": "MATCH p=(n:Base)-[:MemberOf*1..]->(g:Group)\nWHERE (\n g.objectid ENDS WITH '-512' // Domain Admins\n OR g.objectid ENDS WITH '-519' // Enterprise Admins\n OR g.objectid ENDS WITH '-518' // Schema Admins\n)\nAND n.hasspn = true\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -1256,80 +1395,33 @@ ] }, { - "name": "Circular AZ group memberships", - "guid": "b005669c-d8af-47ae-a0f1-4f36cd5334ab", + "name": "Enabled computers inactive for 180 days - MSSQL Failover Cluster", + "guid": "d263e621-7f1b-4efb-ad25-098fc7d4fb72", "prebuilt": false, - "platforms": [ - "Azure" - ], - "category": "Azure Hygiene", - "description": "Detects circular group membership chains where groups are members of themselves through one or more intermediate groups. This causes an administrative complexity.", - "query": "MATCH p=(x:AZGroup)-[:AZMemberOf*2..]->(y:AZGroup)\nWHERE x.objectid=y.objectid\nRETURN p\nLIMIT 100", - "revision": 1, - "resources": [ - "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" - ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] - }, - { - "name": "Shortest paths from Domain Users to Tier Zero / High Value targets", - "guid": "469dc0f3-71b8-41b0-a03b-b4af7874665d", - "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=shortestPath((s:Group)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s.objectid ENDS WITH '-513' AND s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], - "acknowledgements": [] - }, - { - "name": "AdminSDHolder protected Accounts and Groups", - "guid": "5ee2f40e-a55c-4140-ab8a-91746ba3752b", - "prebuilt": false, - "platforms": [ - "Active Directory" - ], - "category": "Domain Information", - "description": "Objects whose permissions are set by SDProp to the template AdminSDHolder object as per MS-ADTS 3.1.1.6.1.2 Protected Objects. Does not exclude objects if specified in dSHeuristics dwAdminSDExMask", - "query": "MATCH (n:Base)-[:MemberOf*0..]->(m:Group)\nWHERE (\n n.objectid =~ \".*-(S-1-5-32-544|S-1-5-32-548|S-1-5-32-549|S-1-5-32-550|S-1-5-32-551|S-1-5-32-552|518|512|519)$\" // Groups\n OR m.objectid =~ \".*-(S-1-5-32-544|S-1-5-32-548|S-1-5-32-549|S-1-5-32-550|S-1-5-32-551|S-1-5-32-552|518|512|519)$\" // Members of groups\n OR n.objectid =~ \".*-(500|502|516|521)$\" // Direct objects\n)\nRETURN n", + "query": "WITH 180 as inactive_days\nMATCH (n:Computer)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND ANY(type IN n.serviceprincipalnames WHERE \n toLower(type) CONTAINS 'mssqlservercluster' OR \n toLower(type) CONTAINS 'mssqlserverclustermgmtapi' OR \n toLower(type) CONTAINS 'msclustervirtualserver')\nRETURN n\nLIMIT 1000", "revision": 1, "resources": [ - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/a0d0b4fa-2895-4c64-b182-ba64ad0f84b8", - "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory" + "https://learn.microsoft.com/en-us/troubleshoot/windows-server/high-availability/troubleshoot-issues-accounts-used-failover-clusters#troubleshoot-password-issues-with-the-cluster-name-account" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Shortest paths from Entra Users to Tier Zero / High Value targets", - "guid": "58089b28-54e0-4fd2-bf66-3db480b00e2f", - "prebuilt": true, - "platforms": [ - "Azure" - ], - "category": "Shortest Paths", - "description": null, - "query": "MATCH p=shortestPath((s:AZUser)-[:AZ_ATTACK_PATHS*1..]->(t:AZBase))\nWHERE (t:AZBase) AND t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator' AND s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], - "acknowledgements": [] - }, - { - "name": "Large default group added to computer-local group", - "guid": "dde133d2-b4d2-4de9-a656-905f3bf066f3", + "name": "Large default groups with outbound control", + "guid": "a334f21a-3d7f-448e-b7ea-1465a3127bce", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Group)-[:MemberOfLocalGroup]->(m:ADLocalGroup)-[:LocalToComputer]->(:Computer)\nWHERE n.objectid =~ \".*-(S-1-5-11|S-1-1-0|S-1-5-32-545|S-1-5-7|-513|-515)$\" // Authenticated Users, Everyone, Users, Anonymous, Domain Users, Domain Computers\nAND NOT m.objectid =~ \".*-(545|574|554)$\" // Users, Certificate Service DCOM Access, Pre-Windows 2000 Compatible Access\nRETURN p", + "query": "MATCH p=(n:Group)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC5|ADCSESC6a|ADCSESC6b|ADCSESC7|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13]->(:Base)\nWHERE n.objectid ENDS WITH \"-513\" // DOMAIN USERS\nOR n.objectid ENDS WITH \"-515\" // DOMAIN COMPUTERS\nOR n.objectid ENDS WITH \"-S-1-5-11\" // AUTHENTICATED USERS\nOR n.objectid ENDS WITH \"-S-1-1-0\" // EVERYONE\nOR n.objectid ENDS WITH \"S-1-5-32-545\" // USERS\nOR n.objectid ENDS WITH \"S-1-5-32-546\" // GUESTS\nOR n.objectid ENDS WITH \"S-1-5-7\" // ANONYMOUS\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -1337,49 +1429,43 @@ ] }, { - "name": "Non-Tier Zero principals with BadSuccessor rights (no prerequisites check)", - "guid": "2b9fb71e-73ad-4061-a2df-40c7132b044d", - "prebuilt": false, + "name": "All Global Administrators", + "guid": "94d7d765-6837-4eb8-aa33-e1c9ef262cdc", + "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Dangerous Privileges", - "description": "Finds non-Tier Zero principals with BadSuccessor rights with no prerequisites check (DC2025 & KDC key).", - "query": "// Find OU control\nMATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base)\n// Exclude Tier Zero\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p LIMIT 1000", + "category": "General", + "description": null, + "query": "MATCH p = (:AZBase)-[:AZGlobalAdmin*1..]->(:AZTenant)\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [ - "https://bsky.app/profile/specterops.io/post/3lpua65qeu22l" - ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "resources": [], + "acknowledgements": [] }, { - "name": "Tier Zero computers not owned by Tier Zero", - "guid": "99d29ded-223a-442b-a0e0-f8b5694c6441", - "prebuilt": false, + "name": "Computers with unsupported operating systems", + "guid": "d06d3b14-0318-4fa9-9639-4b79ccaf3c2c", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Base)-[:Owns]->(:Computer)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", - "revision": 2, + "query": "MATCH (c:Computer)\nWHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*'\nRETURN c\nLIMIT 100", + "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Principals with weak supported Kerberos encryption types", - "guid": "ca329573-2157-41da-ab17-4d122c54b11d", + "name": "ESC8-vulnerable Enterprise CAs", + "guid": "60881923-296c-4702-adf7-a4f059dc9bb8", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH (u:Base)\nWHERE 'DES-CBC-CRC' IN u.supportedencryptiontypes\nOR 'DES-CBC-MD5' IN u.supportedencryptiontypes\nOR 'RC4-HMAC-MD5' IN u.supportedencryptiontypes\nRETURN u", + "query": "MATCH (n:EnterpriseCA)\nWHERE n.hasvulnerableendpoint=true\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [] @@ -1403,15 +1489,34 @@ ] }, { - "name": "Accounts with clear-text password attributes", - "guid": "e303498f-e3d4-489d-8a34-b68e187bc4e7", + "name": "Enrollment rights on published ESC15 certificate templates", + "guid": "78d59fe1-e1a0-4813-adc9-c3c96ac08b66", + "prebuilt": false, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Certificate Services", + "description": "Enrollment rights on certificate templates that meet the requirements for the ADCS ESC15 (EKUwu) attack.", + "query": "MATCH p=(:Base)-[:Enroll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)-[:TrustedForNTAuth]->(:NTAuthStore)-[:NTAuthStoreFor]->(:Domain)\nWHERE ct.enrolleesuppliessubject = True\nAND ct.authenticationenabled = False\nAND ct.requiresmanagerapproval = False\nAND ct.schemaversion = 1\nRETURN p", + "revision": 1, + "resources": [ + "https://x.com/SpecterOps/status/1844800558151901639", + "https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2024-49019" + ], + "acknowledgements": [ + "Jonas B\u00fclow Knudsen, @Jonas_B_K" + ] + }, + { + "name": "Users with non-expiring passwords", + "guid": "212c2a98-53d9-4dfa-b177-42c601452dd1", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Base)\nWHERE n.userpassword IS NOT NULL\nOR n.unixpassword IS NOT NULL\nOR n.unicodepwd IS NOT NULL\nOR n.msSFU30Password IS NOT NULL\nRETURN n", + "query": "MATCH (u:User)\nWHERE u.enabled = true\nAND u.pwdneverexpires = true\nRETURN u\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [ @@ -1419,33 +1524,31 @@ ] }, { - "name": "Non-Tier Zero account with 'Admin Count' flag", - "guid": "e7f703b3-5dba-4aef-8346-4d589be2c828", + "name": "Tier Zero computers not requiring inbound SMB signing", + "guid": "13485477-f026-4b1f-906d-4f2e37364ba4", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Users who were a member of one of AD's built-in administrative groups but are not currently Tier Zero.", - "query": "MATCH (n:User)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.admincount = true\nRETURN n", + "category": "NTLM Relay Attacks", + "description": null, + "query": "MATCH (n:Computer)\nWHERE n.smbsigning = False\nAND ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/windows/win32/adschema/a-admincount" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Non-default delegation on MicrosoftDNS container", - "guid": "008792c0-4458-46a1-a10d-50cdaf95af1e", + "name": "Users with non-default Primary Group membership", + "guid": "93890f88-df2c-4167-a945-a53961d08d00", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Base)-[r]->(m:Container)\nWHERE m.distinguishedname STARTS WITH \"CN=MICROSOFTDNS,CN=SYSTEM,DC=\"\nAND NOT n.name STARTS WITH \"DNSADMINS@\"\nAND NOT n.objectid =~ \"-(512|544|519|9)$\"\nAND r.isacl\nRETURN p", + "query": "MATCH p=(n:User)-[r:MemberOf]->(g:Group)\nWHERE NOT g.objectid ENDS WITH \"-513\" // Domain Users\nAND r.isprimarygroup = true\nAND NOT n.objectid ENDS WITH \"-501\" // Guests account, as it has primaryGroup to Guests\nAND (n.gmsa IS NULL OR n.gmsa = false) // Not gMSA, as it has primaryGroup to Domain Computers\nAND (n.msa IS NULL OR n.msa = false) // Not MSA, as it has primaryGroup to Domain Computers\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -1453,91 +1556,75 @@ ] }, { - "name": "Domain controllers with weak certificate binding enabled", - "guid": "a2444d99-10b5-412d-8fea-4b063cfddd2c", + "name": "Shortest paths from Azure Applications to Tier Zero / High Value targets", + "guid": "60ff7c58-a98e-4bc1-9e32-8378d2db0c43", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Active Directory Certificate Services", + "category": "Shortest Paths", "description": null, - "query": "MATCH p = (s:Computer)-[:DCFor]->(:Domain)\nWHERE s.strongcertificatebindingenforcementraw = 0 OR s.strongcertificatebindingenforcementraw = 1\nRETURN p\nLIMIT 1000", - "revision": 1, + "query": "MATCH p=shortestPath((s:AZApp)-[:AZ_ATTACK_PATHS*1..]->(t:AZBase))\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') AND s<>t\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "DCs vulnerable to NTLM relay to LDAP attacks", - "guid": "3f87e0b0-fc06-4986-a94c-e08781253dc8", + "name": "Shortest paths from Entra Users to Tier Zero / High Value targets", + "guid": "58089b28-54e0-4fd2-bf66-3db480b00e2f", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "NTLM Relay Attacks", + "category": "Shortest Paths", "description": null, - "query": "MATCH p = (dc:Computer)-[:DCFor]->(:Domain)\nWHERE (dc.ldapavailable = True AND dc.ldapsigning = False)\nOR (dc.ldapsavailable = True AND dc.ldapsepa = False)\nOR (dc.ldapavailable = True AND dc.ldapsavailable = True AND dc.ldapsigning = False and dc.ldapsepa = True)\nRETURN p", - "revision": 1, + "query": "MATCH p=shortestPath((s:AZUser)-[:AZ_ATTACK_PATHS*1..]->(t:AZBase))\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "revision": 3, "resources": [], "acknowledgements": [] }, { - "name": "Tier Zero computers at risk of constrained delegation", - "guid": "8641e593-f2f2-48ba-bd45-fbc86e9f632a", - "prebuilt": false, + "name": "Enrollment rights on published certificate templates", + "guid": "a4ae2e54-aad3-4bfd-a12d-90cb8a9cbc86", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p = (n:Computer)<-[:AllowedToDelegate]-(:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Non-Tier Zero principals with BadSuccessor rights (with prerequisites check)", - "guid": "74daaebe-6040-4f7a-9c9a-416faf73dcc3", + "name": "Non-Tier Zero principals with control of AdminSDHolder", + "guid": "4c1e0137-5b7f-48d8-bd09-9db7674bca61", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Dangerous Privileges", - "description": "Finds non-Tier Zero principals with BadSuccessor rights after checking prerequisites check (DC2025 & KDC key).", - "query": "// Find 2025 DCs\nMATCH (dc:Computer)\nWHERE dc.isdc = true AND dc.operatingsystem CONTAINS '2025'\n// Find gMSAs\nMATCH (m:User)\nWHERE m.gmsa = true\n// Find OU control\nMATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base)\n// Confirm domain has a 2025 DC\nWHERE ou.domain = dc.domain\n// Confirm domain KDC key\nAND ou.domain = m.domain\n// Exclude Tier Zero\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p LIMIT 1000", + "description": null, + "query": "MATCH p=(n:Group)-[r:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteOwnerLimitedRights|OwnsLimitedRights]->(m:Container)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND m.name STARTS WITH \"ADMINSDHOLDER@\"\nRETURN p", "revision": 1, "resources": [ - "https://bsky.app/profile/specterops.io/post/3lpua65qeu22l" + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory#adminsdholder" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Servers where Domain Users can RDP", - "guid": "b9a330ae-1d89-44d4-8f74-9ca18e93eb92", - "prebuilt": true, - "platforms": [ - "Active Directory" - ], - "category": "Dangerous Privileges", - "description": null, - "query": "MATCH p=(s:Group)-[:CanRDP]->(t:Computer)\nWHERE s.objectid ENDS WITH '-513' AND toUpper(t.operatingsystem) CONTAINS 'SERVER'\nRETURN p\nLIMIT 1000", - "revision": 1, - "resources": [], - "acknowledgements": [] - }, - { - "name": "Tier Zero computers not requiring inbound SMB signing", - "guid": "13485477-f026-4b1f-906d-4f2e37364ba4", + "name": "Accounts with clear-text password attributes", + "guid": "e303498f-e3d4-489d-8a34-b68e187bc4e7", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "NTLM Relay Attacks", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (n:Computer)\nWHERE n.smbsigning = False\nAND ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", + "query": "MATCH (n:Base)\nWHERE n.userpassword IS NOT NULL\nOR n.unixpassword IS NOT NULL\nOR n.unicodepwd IS NOT NULL\nOR n.msSFU30Password IS NOT NULL\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [ @@ -1545,79 +1632,43 @@ ] }, { - "name": "Paths from Domain Users to Tier Zero / High Value targets", - "guid": "977bec40-565c-40b8-90c8-e3e122c291cd", + "name": "Shortest paths to Domain Admins", + "guid": "f40cb34b-5ec7-44bc-9aa8-a200a4a41f22", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Shortest Paths", "description": null, - "query": "MATCH p=shortestPath((s:Group)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s.objectid ENDS WITH '-513' AND s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", + "query": "MATCH p=shortestPath((t:Group)<-[:AD_ATTACK_PATHS*1..]-(s:Base))\nWHERE t.objectid ENDS WITH '-512' AND s<>t\nRETURN p\nLIMIT 1000", "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated)", - "guid": "609d648f-7fb8-42d3-ad99-626f9ce1f121", + "name": "Shortest paths to Azure Subscriptions", + "guid": "4785b305-c101-461c-80fc-3fb3ff67a8ce", "prebuilt": true, "platforms": [ - "Active Directory", "Azure" ], - "category": "Cross Platform Attack Paths", + "category": "Shortest Paths", "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZHasRole]->(:AZRole)\nRETURN p\nLIMIT 1000", - "revision": 1, + "query": "MATCH p=shortestPath((s:AZBase)-[:AZ_ATTACK_PATHS*1..]->(t:AZSubscription))\nWHERE s<>t\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "Kerberoastable members of Tier Zero / High Value groups", - "guid": "e6da7800-ae06-41cb-80a6-d5421ab2143a", - "prebuilt": true, - "platforms": [ - "Active Directory" - ], - "category": "Kerberos Interaction", - "description": null, - "query": "MATCH (u:User)\nWHERE (u:Tag_Tier_Zero) AND u.hasspn=true\nAND u.enabled = true\nAND NOT u.objectid ENDS WITH '-502'\nAND NOT COALESCE(u.gmsa, false) = true\nAND NOT COALESCE(u.msa, false) = true \nRETURN u\nLIMIT 100", - "revision": 1, - "resources": [ - "https://attack.mitre.org/techniques/T1558/003/" - ], - "acknowledgements": [] - }, - { - "name": "Domain controllers with UPN certificate mapping enabled", - "guid": "799ea3ce-572b-4594-98c4-041aa2ae6176", - "prebuilt": true, - "platforms": [ - "Active Directory" - ], - "category": "Active Directory Certificate Services", - "description": null, - "query": "MATCH p = (s:Computer)-[:DCFor]->(:Domain)\nWHERE s.certificatemappingmethodsraw IN [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]\nRETURN p\nLIMIT 1000", - "revision": 1, - "resources": [ - "https://support.microsoft.com/en-us/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16", - "https://specterops.io/blog/2024/02/28/adcs-esc14-abuse-technique/" - ], - "acknowledgements": [ - "Jonas B\u00fclow Knudsen, @Jonas_B_K" - ] - }, - { - "name": "Users with non-expiring passwords", - "guid": "212c2a98-53d9-4dfa-b177-42c601452dd1", + "name": "Enabled users inactive for 180 days", + "guid": "71972f3c-b32d-4023-a841-5cc8cc1c1867", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (u:User)\nWHERE u.enabled = true\nAND u.pwdneverexpires = true\nRETURN u\nLIMIT 100", + "query": "WITH 180 as inactive_days\nMATCH (n:User)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nRETURN n\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [ @@ -1625,483 +1676,459 @@ ] }, { - "name": "Object name conflict", - "guid": "c561c4f8-ea45-453f-85a2-3fc2e20e7f8c", + "name": "Tier Zero users not member of Protected Users", + "guid": "543eb01d-9fa3-4b8f-a936-b46bbfdaa2ae", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "When two objects are created with the same Relative Distinguished Name (RDN) in the same parent Organizational Unit or container, the conflict is recognized by the system when one of the new objects replicates to another domain controller. When this happens, one of the objects is renamed with 'CNF'", - "query": "MATCH (n:Base)\nWHERE n.distinguishedname CONTAINS 'CNF:'\nRETURN n", + "description": null, + "query": "MATCH (m:User)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nOPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base)\nWHERE g.objectid ENDS WITH '-525'\nWITH m, COLLECT(n) AS matchingNs\nWHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid)\nRETURN m", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/archive/technet-wiki/15435.active-directory-duplicate-object-name-resolution" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Enrollment rights on published ESC1 certificate templates", - "guid": "2af855bc-f48f-4b22-9839-627d8231e425", + "name": "Computers with the outgoing NTLM setting set to Deny all", + "guid": "a9ddca74-feeb-4dbf-8b0f-de08b3cfa8a6", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE ct.enrolleesuppliessubject = True\nAND ct.authenticationenabled = True\nAND ct.requiresmanagerapproval = False\nAND (ct.authorizedsignatures = 0 OR ct.schemaversion = 1)\nRETURN p\nLIMIT 1000", + "query": "MATCH (c:Computer)\nWHERE c.restrictoutboundntlm = True\nRETURN c LIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "All members of high privileged roles", - "guid": "3df24d92-dd12-4125-811b-e696b098f60e", + "name": "Users with passwords not rotated in over 1 year", + "guid": "be70d1bd-b7eb-40b0-971c-eefc50eca032", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "General", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(t:AZRole)<-[:AZHasRole|AZMemberOf*1..2]-(:AZBase)\nWHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator'\nRETURN p\nLIMIT 1000", + "query": "WITH 365 as days_since_change\nMATCH (u:User)\nWHERE u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Potential GPO 'Apply' misconfiguration", - "guid": "f5f2455e-afdc-4708-9a34-98f539ce52d8", - "prebuilt": true, + "name": "Tier Zero users with passwords not rotated in over 1 year", + "guid": "5e0d69b1-37d1-43ae-ac5d-f297f312fab5", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", - "description": "In Active Directory, GPO's are applied to objects in the Group Policy Management Console by ticking \"Allow - Apply group policy\", but administrators can mistakenly tick \"Allow - Write\" or \"Allow - Full Control\" resulting in a misconfigured GPO that allows a principal to compromise other principals the GPO also applies to. Results are potential risks and must be audited for for correctness.", - "query": "MATCH p=(n:Base)-[:GenericAll|GenericWrite]->(g:GPO)\n\n// Exclude Enterprise Admins and Domain Admins\nWHERE NOT n.objectid =~ \"-(519|512)$\"\n\n// Exclude unresolved SIDs\nAND NOT (n.distinguishedname IS NULL)\n\n// Asset description may reveal if it's a delegation group (false-positive) or a filter group (true-positive)\n//AND n.description is not null\n//AND n.description =~ \"(?i)apply\"\n\nRETURN p\nLIMIT 1000", - "revision": 2, + "category": "Active Directory Hygiene", + "description": null, + "query": "WITH 365 as days_since_change\nMATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0')\nAND u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u\nLIMIT 100", + "revision": 1, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Principal with SPN keyword", - "guid": "38a9c4c9-3d70-453f-a017-cbfd35ed9917", + "name": "Trace ACE inheritance", + "guid": "8c5454df-3ae8-412c-b271-3c4c55df7141", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Kerberos Interaction", - "description": "Finds service accounts used with a specific Kerberos-enabled service or all service accounts running on a Kerberos-enabled service on a specific server.", - "query": "// Replace keyword with a service type or server name (not FQDN)\nWITH \"KEYWORD\" as SPNKeyword\nMATCH (n:User)\nWHERE ANY(keyword IN n.serviceprincipalnames WHERE toUpper(keyword) CONTAINS toUpper(SPNKeyword))\nRETURN n", + "category": "Domain Information", + "description": "When BloodHound shows that an inherited ACE applies to an object it does not show the source/where it is inherited from from (OU, Container, Domain root) - the source is where it should be remediated. This query can sometimes find the source of an inherited ACE, but only works if the ACE is set to also apply to the source itself.", + "query": "// Replace INSERT_OBJECT_ID with the affected principal\n// Replace 'GenericAll' with the specific edge you're tracing\nWITH \"INSERT_OBJECT_ID\" as OID\nMATCH p=()-[:GenericAll {isacl:true,isinherited:false}]->()-[:Contains*1..]->(:Base{objectid:OID})\nWHERE NONE(ou in NODES(p) WHERE ou:OU AND ou.isaclprotected IS NOT NULL)\nRETURN p", "revision": 1, - "resources": [ - "https://adsecurity.org/?page_id=183" - ], + "resources": [], "acknowledgements": [ - "Ryan, @haus3c" + "Walter.Legowski, @SadProcessor" ] }, { - "name": "All Schema Admins", - "guid": "76d8e61d-7a86-40ff-8a85-fd37f1e2563f", + "name": "Foreign Service Principals With any Abusable MS Graph App Role Assignment", + "guid": "d7a180c8-5624-4fc1-a407-deeb2ad3054c", "prebuilt": false, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Domain Information", - "description": null, - "query": "MATCH p=(n:Base)-[:MemberOf*1..]->(m:Group)\nWHERE (n:User OR n:Computer)\nAND m.objectid ENDS WITH \"-518\" // Schema Admins\nRETURN p", + "category": "Dangerous Privileges", + "description": "MS Graph app role assignments provide significant power within an Entra ID tenant, similar to an Admin role.", + "query": "MATCH p = (sp1:AZServicePrincipal)-[r:AZMGGroupMember_ReadWrite_All|AZMGServicePrincipalEndpoint_ReadWrite_All|AZMGAppRoleAssignment_ReadWrite_All|AZMGGroup_ReadWrite_All|AZMGDirectory_ReadWrite_All|AZMGRoleManagement_ReadWrite_Directory]->(sp2:AZServicePrincipal)\nWHERE toUpper(sp1.appownerorganizationid) <> toUpper(sp1.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp1.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [], + "resources": [ + "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" + ], "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" + "Stephen Hinck" ] }, { - "name": "Members of Allowed RODC Password Replication Group", - "guid": "19fc5acd-e30a-4038-a5b5-2e0494f93373", + "name": "Domains with functional level not the latest version", + "guid": "3da9d14a-f1cb-4df7-b3da-8d73ff5c401b", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(:Base)-[:MemberOf*1..]->(m:Group)\nWHERE m.objectid ENDS WITH \"-571\"\nRETURN p", - "revision": 2, + "query": "MATCH (n:Domain)\nWHERE toString(n.functionallevel) IN ['2008','2003','2003 Interim','2000 Mixed/Native']\nRETURN n", + "revision": 1, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Tier Zero / High Value enabled users not requiring smart card authentication", - "guid": "867f9f17-c149-4c4b-ad84-9a807622ff8c", - "prebuilt": true, + "name": "KRBTGT accounts with passwords not rotated in over 1 year", + "guid": "1b3ae310-ffa7-4ce5-a37f-6111aef600c8", + "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0')\nAND u.enabled = true\nAND u.smartcardrequired = false\nAND NOT u.name STARTS WITH 'MSOL_' // Removes false positive, Entra sync\nAND NOT u.name STARTS WITH 'PROVAGENTGMSA' // Removes false positive, Entra sync\nAND NOT u.name STARTS WITH 'ADSYNCMSA_' // Removes false positive, Entra sync\nRETURN u", + "query": "MATCH (n:User)\nWHERE (n.objectid ENDS WITH '-502'\nOR n.name STARTS WITH 'AZUREADKERBEROS.'\nOR n.name STARTS WITH 'KRBTGT_AZUREAD@')\nAND n.pwdlastset < (datetime().epochseconds - (365 * 86400))\nRETURN n", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Computers with the WebClient running", - "guid": "51107ad1-f0bc-43d3-a561-5cee471ca196", - "prebuilt": true, + "name": "Tier Zero computers at risk of resource-based constrained delegation", + "guid": "4dc97cf4-3c03-4fe6-8a8b-4f665c67e1e5", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "NTLM Relay Attacks", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (c:Computer)\nWHERE c.webclientrunning = True\nRETURN c LIMIT 1000", + "query": "MATCH p = (n:Computer)<-[:AllowedToAct]-(:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "On-Prem Users synced to Entra Users with Entra Group Membership", - "guid": "edb575df-2048-4ef0-a0e4-168544a496e9", + "name": "Domains with smart card accounts where smart account passwords do not expire", + "guid": "97e05e67-5961-4aba-a8e7-fe5f92334035", "prebuilt": true, "platforms": [ - "Active Directory", - "Azure" + "Active Directory" ], - "category": "Cross Platform Attack Paths", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)\nRETURN p\nLIMIT 1000", + "query": "MATCH (s:Domain)-[:Contains*1..]->(t:Base)\nWHERE s.expirepasswordsonsmartcardonlyaccounts = false\nAND t.enabled = true\nAND t.smartcardrequired = true\nRETURN s", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Computers where Domain Users can read LAPS passwords", - "guid": "aa4bfa95-e7b9-4d56-8f35-f34f04d7b6f4", - "prebuilt": true, + "name": "Domains allowing unauthenticated domain enumeration", + "guid": "41a08d76-f8a5-4296-ad19-464c4c5c69fe", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(s:Group)-[:AllExtendedRights|ReadLAPSPassword]->(:Computer)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE (n.objectid ENDS WITH \"S-1-5-7\" // Anonymous\nOR n.objectid ENDS WITH \"S-1-1-0\") // Everyone\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Domains without Protected Users group", - "guid": "8c3e0811-a31b-45b4-a29d-1dce80fa2c5f", + "name": "Computers with passwords older than the default maximum password age", + "guid": "185c5010-8d4f-4f9b-b24e-831707dddfca", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": null, - "query": "MATCH (n:Domain)\nWHERE n.collected = true\nOPTIONAL MATCH (m:Group)\nWHERE m.name ENDS WITH n.name\nAND m.objectid ENDS WITH '-525'\nWITH n, m\nWHERE m IS NULL\nRETURN n", + "category": "Active Directory Hygiene", + "description": "Machine account passwords are regularly changed for security purposes. Starting with Windows 2000-based computers, the machine account password automatically changes every 30 days.", + "query": "WITH 60 as rotation_period\nMATCH (n:Computer)\nWHERE n.pwdlastset < (datetime().epochseconds - (rotation_period * 86400)) // password not rotated\nAND n.enabled = true // enabled computers\nAND n.whencreated < (datetime().epochseconds - (rotation_period * 86400)) // exclude recently created computers\nAND n.lastlogontimestamp > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Replicated value)\nAND n.lastlogon > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Non-replicated value)\nRETURN n", "revision": 1, - "resources": [], + "resources": [ + "https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-machine-account-password" + ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Shortest paths from Owned objects to Tier Zero", - "guid": "dfaa8e8f-2c79-4e92-a291-b1347f6e83b0", - "prebuilt": true, + "name": "Sessions across trusts", + "guid": "aea7ac64-1f51-407b-b0ee-19fd30075794", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", - "description": null, - "query": "// MANY TO MANY SHORTEST PATH QUERIES USE EXCESSIVE SYSTEM RESOURCES AND TYPICALLY WILL NOT COMPLETE\nMATCH p=shortestPath((s:Tag_Owned)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE s<>t\nAND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", - "revision": 2, + "category": "Domain Information", + "description": "Users logging on across a trust, the users originate from trusted domains.", + "query": "MATCH p=(trustedDomainPrincipal:Computer)-[r:HasSession]->(trustingDomainPrincipal:User)\nWHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid\nRETURN p\nLIMIT 1000", + "revision": 1, "resources": [], - "acknowledgements": [] + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "All Domain Admins", - "guid": "0596dba7-9180-49a0-aa54-00243240037c", + "name": "Disabled Tier Zero / High Value principals", + "guid": "d65a801f-d3ef-4b7e-8030-99ebfd6dad12", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p = (t:Group)<-[:MemberOf*1..]-(a)\nWHERE (a:User or a:Computer) and t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", + "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = false\nAND NOT n.objectid ENDS WITH '-502' // Removes false positive, KRBTGT\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nRETURN n\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Domains allowing unauthenticated rootDSE searches and binds", - "guid": "ebc79aa4-e816-4be8-93fe-a0b30dbc771d", + "name": "Domains with a minimum default password policy length less than 15 characters", + "guid": "7d258d2d-a43d-4a90-85d7-71c946ae5fd7", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "Checks the fLDAPBlockAnonOps flag of dSHeuristics.", - "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{6}[^2].*\"\nRETURN n", + "description": null, + "query": "MATCH (n:Domain)\nWHERE n.minpwdlength < 15\nRETURN n", "revision": 1, "resources": [ - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" + "https://pages.nist.gov/800-63-3/sp800-63b.html" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Map Azure Management structure", - "guid": "c1bb109e-e6a4-4c91-864f-f78e1e42615e", + "name": "Domains allowing unauthenticated NSPI RPC binds", + "guid": "a950fdab-5934-4c69-a88b-e2e0e3da9d52", "prebuilt": false, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Kerberos Interaction", - "description": "Maps the structure of Azure Management", - "query": "MATCH p = (:AZTenant)-[:AZContains*1..]->(:AZResourceGroup)\nRETURN p\nLIMIT 1000", + "category": "Active Directory Hygiene", + "description": "Checks the fAllowAnonNSPI flag of dSHeuristics.", + "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{7}[^0].*\"\nRETURN n", "revision": 1, "resources": [ - "https://learn.microsoft.com/en-us/azure/governance/management-groups/overview" + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Foreign Service Principals With an EntraID Admin Role", - "guid": "b6235820-4e0d-4dfa-af5b-729b5644feb5", + "name": "Overprivileged Microsoft Entra Connect accounts", + "guid": "9e6e75b4-9ecc-45d4-a39b-b6427b813f0a", "prebuilt": false, "platforms": [ + "Active Directory", "Azure" ], - "category": "Dangerous Privileges", - "description": "Entra ID admin roles grant significant control over a tenant environment, even if the role is not a default Tier Zero / High Value role", - "query": "MATCH p = (sp:AZServicePrincipal)-[:AZHasRole]->(r:AZRole)\nWHERE toUpper(sp.appownerorganizationid) <> toUpper(sp.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", + "category": "Active Directory Hygiene", + "description": "Legacy MSOL accounts were by default deployed with Domain Admins or Enterprise Admins membership.", + "query": "MATCH p=(n:User)-[:MemberOf*1..]->(g:Group)\nWHERE n.name STARTS WITH \"MSOL_\"\nAND (g.objectid ENDS WITH \"-512\" // Domain Admins\nOR g.objectid ENDS WITH \"-519\") // Entterprise Admins\nRETURN p", "revision": 1, "resources": [ - "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" + "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/reference-connect-accounts-permissions" ], "acknowledgements": [ - "Stephen Hinck" + "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "All DNSAdmins", - "guid": "183fb320-f3ae-4ab3-a090-3f9a7db692e1", + "name": "Users with logon scripts stored in a trusted domain", + "guid": "8d94d3f3-3d53-4939-a206-3c0a4dd3f646", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Base)-[:MemberOf]->(g:Group) \nWHERE n.name STARTS WITH \"DNSADMINS@\"\nRETURN p", - "revision": 1, + "query": "MATCH (n:User)\nWHERE n.logonscript IS NOT NULL\nMATCH (d:Domain)<-[:SameForestTrust|CrossForestTrust]-(:Domain)-[:Contains*1..]->(n)\nWITH n,last(split(d.name, '@')) AS domain\nWHERE toUpper(n.logonscript) STARTS WITH (\"\\\\\\\\\" + domain + \"\\\\\")\nRETURN n", + "revision": 2, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Domains where any user can join a computer to the domain", - "guid": "421921fa-bc0f-4659-9680-b7481adcb132", - "prebuilt": true, - "platforms": [ - "Active Directory" - ], - "category": "Active Directory Hygiene", - "description": null, - "query": "MATCH (n:Domain)\nWHERE n.machineaccountquota > 0\nRETURN n", - "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/default-workstation-numbers-join-domain", - "https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/add-workstations-to-domain" - ], - "acknowledgements": [] - }, - { - "name": "On-Prem Users synced to Entra Users with Entra Admin Roles (direct)", - "guid": "de717635-d31f-4fbd-930b-b4dac0f22118", - "prebuilt": true, - "platforms": [ - "Active Directory", - "Azure" - ], - "category": "Cross Platform Attack Paths", - "description": null, - "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZHasRole]->(:AZRole)\nRETURN p\nLIMIT 1000", - "revision": 1, - "resources": [], - "acknowledgements": [] - }, - { - "name": "Tier Zero computers with passwords older than the default maximum password age", - "guid": "b6d6d0bf-130e-4719-996b-adc29bba36e9", + "name": "Domains without Protected Users group", + "guid": "8c3e0811-a31b-45b4-a29d-1dce80fa2c5f", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Domain Information", "description": null, - "query": "MATCH (n:Computer)\nWHERE n.enabled = true\nAND n.whencreated < (datetime().epochseconds - (60 * 3 * 86400))\nAND n.pwdlastset < (datetime().epochseconds - (60 * 3 * 86400))\nAND ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", - "revision": 2, + "query": "MATCH (n:Domain)\nWHERE n.collected = true\nOPTIONAL MATCH (m:Group)\nWHERE m.name ENDS WITH n.name\nAND m.objectid ENDS WITH '-525'\nWITH n, m\nWHERE m IS NULL\nRETURN n", + "revision": 1, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Shortest paths from Owned objects", - "guid": "e370a01d-c129-4f19-b88d-9479cbe00028", + "name": "AS-REP Roastable users (DontReqPreAuth)", + "guid": "2570e359-dec1-419d-b0dc-a204bd64ee42", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", + "category": "Kerberos Interaction", "description": null, - "query": "MATCH p=shortestPath((s:Base)-[:AD_ATTACK_PATHS*1..]->(t:Base))\nWHERE (s:Tag_Owned)\nAND s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], + "query": "MATCH (u:User)\nWHERE u.dontreqpreauth = true\nAND u.enabled = true\nRETURN u\nLIMIT 100", + "revision": 1, + "resources": [ + "https://attack.mitre.org/techniques/T1558/004/" + ], "acknowledgements": [] }, { - "name": "Shortest paths to Domain Admins from Kerberoastable users", - "guid": "bd163361-1e05-47c7-908b-962aef251535", + "name": "On-Prem Users synced to Entra Users with Azure RM Roles (direct)", + "guid": "8569113b-e42e-49b0-a968-53bcf0ccd970", "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Shortest Paths", + "category": "Cross Platform Attack Paths", "description": null, - "query": "MATCH p=shortestPath((s:User)-[:AD_ATTACK_PATHS*1..]->(t:Group))\nWHERE s.hasspn=true\nAND s.enabled = true\nAND NOT s.objectid ENDS WITH '-502'\nAND NOT COALESCE(s.gmsa, false) = true\nAND NOT COALESCE(s.msa, false) = true\nAND t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", - "revision": 2, + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase)\nRETURN p\nLIMIT 1000", + "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Usage of built-in domain Administrator account", - "guid": "35b1206f-871b-44aa-a601-c5258060dfcf", + "name": "Foreign Service Principals With an EntraID Admin Role", + "guid": "b6235820-4e0d-4dfa-af5b-729b5644feb5", "prebuilt": false, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Active Directory Hygiene", - "description": "Usage of Active Directory's built-in Administrator account is a sign that the account is not only used for break-glass purposes.", - "query": "MATCH (n:User)\nWHERE n.objectid ENDS WITH \"-500\"\nAND (\n n.lastlogontimestamp > (datetime().epochseconds - (60 * 86400)) OR\n n.lastlogon > (datetime().epochseconds - (60 * 86400))\n)\nAND NOT n.whencreated > (datetime().epochseconds - (60 * 86400))\nRETURN n", + "category": "Dangerous Privileges", + "description": "Entra ID admin roles grant significant control over a tenant environment, even if the role is not a default Tier Zero / High Value role", + "query": "MATCH p = (sp:AZServicePrincipal)-[:AZHasRole]->(r:AZRole)\nWHERE toUpper(sp.appownerorganizationid) <> toUpper(sp.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [], + "resources": [ + "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" + ], "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" + "Stephen Hinck" ] }, { - "name": "Enrollment rights on published ESC15 certificate templates", - "guid": "78d59fe1-e1a0-4813-adc9-c3c96ac08b66", + "name": "Direct Principal Rights Assignment", + "guid": "1d9c6ae3-38fc-4089-b5ad-fc3be0fa8eec", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", - "description": "Enrollment rights on certificate templates that meet the requirements for the ADCS ESC15 (EKUwu) attack.", - "query": "MATCH p=(:Base)-[:Enroll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)-[:TrustedForNTAuth]->(:NTAuthStore)-[:NTAuthStoreFor]->(:Domain)\nWHERE ct.enrolleesuppliessubject = True\nAND ct.authenticationenabled = False\nAND ct.requiresmanagerapproval = False\nAND ct.schemaversion = 1\nRETURN p", + "category": "Active Directory Hygiene", + "description": "This query identifies rights assigned directly to users or computers instead of groups. Active Directory best practice requires granting rights to groups, then adding users as group members. This role-based access control (RBAC) approach ensures permissions are easily auditable and manageable. Results include inherited rights, which must be modified at the parent container level.", + "query": "MATCH p=(n:Base)-[r:GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13]->(:Base)\nWHERE (n:User OR n:Computer) \nRETURN p\nLIMIT 1000", "revision": 1, "resources": [ - "https://x.com/SpecterOps/status/1844800558151901639", - "https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2024-49019" + "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" ], "acknowledgements": [ - "Jonas B\u00fclow Knudsen, @Jonas_B_K" + "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Tier Zero / High Value external Entra ID users", - "guid": "20e07417-d286-4dca-a962-568f2b262f65", + "name": "Public Key Services container", + "guid": "07e94492-71aa-4665-ab8c-e7aec25906cd", "prebuilt": true, "platforms": [ - "Azure" + "Active Directory" ], - "category": "Azure Hygiene", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH (n:AZUser)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.name CONTAINS '#EXT#@'\nRETURN n\nLIMIT 100", + "query": "MATCH p = (c:Container)-[:Contains*..]->(:Base)\nWHERE c.distinguishedname starts with 'CN=PUBLIC KEY SERVICES,CN=SERVICES,CN=CONFIGURATION,DC='\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "ACEs across trusts", - "guid": "c902d3b4-1a75-4335-acd7-28246dab746d", - "prebuilt": false, + "name": "Enabled Tier Zero / High Value principals inactive for 60 days", + "guid": "72550bcb-3c4f-463d-8973-91a49163dc5a", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "ACEs granted across a trust, the ACEs are set on trusting objects and the rights are granted to objects from trusted domains.", - "query": "MATCH p=(trustedDomainPrincipal:Base)-[r]->(trustingDomainPrincipal:Base)\nWHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid\nAND r.isacl\nRETURN p\nLIMIT 1000", + "category": "Active Directory Hygiene", + "description": null, + "query": "WITH 60 as inactive_days\nMATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT\nAND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator\nAND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO\nRETURN n", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, - { - "name": "Public Key Services container", - "guid": "07e94492-71aa-4665-ab8c-e7aec25906cd", + { + "name": "Computers not requiring inbound SMB signing", + "guid": "6b1fcfb6-b010-41a2-9d31-f9872fe994ff", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH p = (c:Container)-[:Contains*..]->(:Base)\nWHERE c.distinguishedname starts with 'CN=PUBLIC KEY SERVICES,CN=SERVICES,CN=CONFIGURATION,DC='\nRETURN p\nLIMIT 1000", + "query": "MATCH (n:Computer)\nWHERE n.smbsigning = False\nRETURN n", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Computers where Domain Users are local administrators", - "guid": "d43a7bdc-33c6-4a39-a3bb-24115749e595", + "name": "Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled", + "guid": "96e70597-2d74-4503-a624-f1e30b642894", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH p=(s:Group)-[:AdminTo]->(:Computer)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(eca:EnterpriseCA)\nWHERE eca.isuserspecifiessanenabled = True\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Accounts with SID History to a same-domain account", - "guid": "275d2d58-0cad-4cad-8103-e0874cece666", - "prebuilt": false, + "name": "Servers where Domain Users can RDP", + "guid": "b9a330ae-1d89-44d4-8f74-9ca18e93eb92", + "prebuilt": true, "platforms": [ "Active Directory" ], "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE n.domainsid = m.domainsid\nRETURN p", + "query": "MATCH p=(s:Group)-[:CanRDP]->(t:Computer)\nWHERE s.objectid ENDS WITH '-513' AND toUpper(t.operatingsystem) CONTAINS 'SERVER'\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Users with non-default Primary Group membership", - "guid": "93890f88-df2c-4167-a945-a53961d08d00", + "name": "Accounts with SID History", + "guid": "8172d52c-a975-49bd-9180-5b6efc59c9ab", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:User)-[r:MemberOf]->(g:Group)\nWHERE NOT g.objectid ENDS WITH \"-513\" // Domain Users\nAND r.isprimarygroup = true\nAND NOT n.objectid ENDS WITH \"-501\" // Guests account, as it has primaryGroup to Guests\nAND (n.gmsa IS NULL OR n.gmsa = false) // Not gMSA, as it has primaryGroup to Domain Computers\nAND (n.msa IS NULL OR n.msa = false) // Not MSA, as it has primaryGroup to Domain Computers\nRETURN p", + "query": "MATCH p=(:Base)-[:HasSIDHistory]->(:Base)\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -2109,63 +2136,59 @@ ] }, { - "name": "Domains without Microsoft LAPS computers", - "guid": "f9b440b5-732c-4ed3-b6d2-83857db17e1a", - "prebuilt": false, + "name": "Disabled Tier Zero / High Value principals", + "guid": "860d5c2d-84fe-4c85-80de-e0a9badbd0e7", + "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Domain Information", + "category": "Azure Hygiene", "description": null, - "query": "MATCH (d:Domain)\nOPTIONAL MATCH (c:Computer)\nWHERE c.domainsid = d.objectid AND c.haslaps = true\nWITH d, COLLECT(c) AS computers\nWHERE SIZE(computers) = 0\nRETURN d", + "query": "MATCH (n:AZBase)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.enabled = false\nRETURN n\nLIMIT 100", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Enrollment rights on published certificate templates", - "guid": "a4ae2e54-aad3-4bfd-a12d-90cb8a9cbc86", + "name": "Shortest paths to Tier Zero / High Value targets", + "guid": "237aac58-8641-4703-a9f7-001d69546fd8", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "Shortest Paths", "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nRETURN p\nLIMIT 1000", - "revision": 1, + "query": "MATCH p=shortestPath((s)-[:AD_ATTACK_PATHS*1..]->(t:Tag_Tier_Zero))\nWHERE s<>t\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "Computers with passwords older than the default maximum password age", - "guid": "185c5010-8d4f-4f9b-b24e-831707dddfca", + "name": "Tier Zero computers with the WebClient running", + "guid": "27a6f917-8ed4-4e2e-9b38-41a4b6de1b14", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "Machine account passwords are regularly changed for security purposes. Starting with Windows 2000-based computers, the machine account password automatically changes every 30 days.", - "query": "WITH 60 as rotation_period\nMATCH (n:Computer)\nWHERE n.pwdlastset < (datetime().epochseconds - (rotation_period * 86400)) // password not rotated\nAND n.enabled = true // enabled computers\nAND n.whencreated < (datetime().epochseconds - (rotation_period * 86400)) // exclude recently created computers\nAND n.lastlogontimestamp > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Replicated value)\nAND n.lastlogon > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Non-replicated value)\nRETURN n", + "description": null, + "query": "MATCH (c:Computer)\nWHERE c.webclientrunning = True\nAND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN c LIMIT 1000", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-machine-account-password" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Smart card accounts with passwords not rotated in over 1 year", - "guid": "7e56f2e7-79c3-4f0d-aa3e-14cf3de7ab73", + "name": "Domain Controllers allowing NTLMv1 or LM authentication", + "guid": "4b42513c-f89d-47ff-8d98-908af49d2b48", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH (n:Base)\nWHERE n.pwdlastset < (datetime().epochseconds - (365 * 86400))\nAND n.enabled = true\nAND n.smartcardrequired = true\nRETURN n", + "query": "MATCH (dc:Computer)\nWHERE dc.isdc = true\nAND (dc.lmcompatibilitylevel IS NOT NULL AND NOT dc.lmcompatibilitylevel = 5)\nRETURN dc", "revision": 1, "resources": [], "acknowledgements": [ @@ -2173,89 +2196,90 @@ ] }, { - "name": "Users with passwords not rotated in over 1 year", - "guid": "be70d1bd-b7eb-40b0-971c-eefc50eca032", + "name": "Computers where Domain Users are local administrators", + "guid": "d43a7bdc-33c6-4a39-a3bb-24115749e595", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "WITH 365 as days_since_change\nMATCH (u:User)\nWHERE u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400))\nAND NOT u.pwdlastset IN [-1.0, 0.0]\nRETURN u\nLIMIT 100", + "query": "MATCH p=(s:Group)-[:AdminTo]->(:Computer)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Shortest paths to Domain Admins", - "guid": "f40cb34b-5ec7-44bc-9aa8-a200a4a41f22", - "prebuilt": true, + "name": "AS-REP Roastable Tier Zero users (DontReqPreAuth)", + "guid": "6d51e4dc-e1ad-477a-b6c6-324f18f03120", + "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=shortestPath((t:Group)<-[:AD_ATTACK_PATHS*1..]-(s:Base))\nWHERE t.objectid ENDS WITH '-512' AND s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, - "resources": [], - "acknowledgements": [] + "query": "MATCH (n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.dontreqpreauth = true\nRETURN n", + "revision": 1, + "resources": [ + "https://attack.mitre.org/techniques/T1558/004/" + ], + "acknowledgements": [ + "Martin Sohn Christensen, @martinsohndk" + ] }, { - "name": "Shortest paths to systems trusted for unconstrained delegation", - "guid": "16a9e47b-45f8-4514-b409-771bb5186142", + "name": "All Domain Admins", + "guid": "0596dba7-9180-49a0-aa54-00243240037c", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Shortest Paths", + "category": "Domain Information", "description": null, - "query": "MATCH p=shortestPath((s)-[:AD_ATTACK_PATHS*1..]->(t:Computer))\nWHERE t.unconstraineddelegation = true AND s<>t\nRETURN p\nLIMIT 1000", - "revision": 2, + "query": "MATCH p = (t:Group)<-[:MemberOf*1..]-(a)\nWHERE (a:User or a:Computer) and t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", + "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Nested groups within Tier Zero / High Value", - "guid": "8e541e75-df1d-423f-b429-4bbf0403a338", + "name": "All service principals with Microsoft Graph privilege to grant arbitrary App Roles", + "guid": "e6d6b5da-89da-4514-a409-2d6e368397da", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Active Directory Hygiene", + "category": "Microsoft Graph", "description": null, - "query": "MATCH p=(t:Group)<-[:MemberOf*..]-(s:Group)\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT s.objectid ENDS WITH '-512' // Domain Admins\nAND NOT s.objectid ENDS WITH '-519' // Enterprise Admins\nRETURN p\nLIMIT 1000", + "query": "MATCH p=(:AZServicePrincipal)-[:AZMGGrantAppRoles]->(:AZTenant)\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Collection health of DC Registry Data", - "guid": "3f0fa2f3-fbdf-42c0-9e7d-97e689009161", - "prebuilt": false, + "name": "On-Prem Users synced to Entra Users with Entra Group Membership", + "guid": "edb575df-2048-4ef0-a0e4-168544a496e9", + "prebuilt": true, "platforms": [ - "Active Directory" + "Active Directory", + "Azure" ], - "category": "Domain Information", - "description": "BloodHound's ADCS analysis requires collecting CA registry data to increase accuracy/enable more edges. Collection by default requires SharpHound has Administrators membership. Requires SharpHound v2.3.5 or above. It only requires one misconfigured DC to potentially a full forest compromise by any principal. DCs returned by this query have not been collected.", - "query": "MATCH p=(:Domain)<-[:DCFor]-(c:Computer)\nWHERE c.strongcertificatebindingenforcementraw IS NULL\n// Exclude inactive DCs\nAND c.enabled = true\nAND c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400))\nRETURN p", + "category": "Cross Platform Attack Paths", + "description": null, + "query": "MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [ - "https://bloodhound.specterops.io/collect-data/enterprise-collection/permissions#dc-registry" - ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "resources": [], + "acknowledgements": [] }, { - "name": "Domains with more than 50 Tier Zero accounts", - "guid": "f046e95a-5f84-4e83-bcda-6e83f3d8e21a", + "name": "Enabled computers inactive for 180 days", + "guid": "0768e810-1e1e-4319-a216-76d9c2058644", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH (d:Domain)-[:Contains*1..]->(n:Base)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nWITH d, COUNT(n) AS adminCount\nWHERE adminCount > 50\nRETURN d", + "query": "WITH 180 as inactive_days\nMATCH (n:Computer)\nWHERE n.enabled = true\nAND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value\nAND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value\nAND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals\nAND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT\nAND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO\nRETURN n\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [ @@ -2263,61 +2287,78 @@ ] }, { - "name": "Non-Tier Zero account with excessive control", - "guid": "944cecfe-519b-4318-b226-e8520161b454", + "name": "Principal with SPN keyword", + "guid": "38a9c4c9-3d70-453f-a017-cbfd35ed9917", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", - "description": "Returns non-Tier Zero principals with >= 1000 direct rights to other principals. This does not include rights from group memberships.", - "query": "MATCH (n:Base)-[r:AD_ATTACK_PATHS]->(m:Base)\nWHERE NOT r:MemberOf\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nWITH n, COLLECT(DISTINCT(m)) AS endNodes\nWHERE SIZE(endNodes) >= 1000\nRETURN n", - "revision": 3, - "resources": [], + "category": "Kerberos Interaction", + "description": "Finds service accounts used with a specific Kerberos-enabled service or all service accounts running on a Kerberos-enabled service on a specific server.", + "query": "// Replace keyword with a service type or server name (not FQDN)\nWITH \"KEYWORD\" as SPNKeyword\nMATCH (n:User)\nWHERE ANY(keyword IN n.serviceprincipalnames WHERE toUpper(keyword) CONTAINS toUpper(SPNKeyword))\nRETURN n", + "revision": 1, + "resources": [ + "https://adsecurity.org/?page_id=183" + ], "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" + "Ryan, @haus3c" ] }, { - "name": "AS-REP Roastable users (DontReqPreAuth)", - "guid": "2570e359-dec1-419d-b0dc-a204bd64ee42", + "name": "Non-default permissions on IssuancePolicy nodes", + "guid": "b2280665-c91b-448c-8c0f-97d1f38b6f59", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Kerberos Interaction", + "category": "Active Directory Certificate Services", "description": null, - "query": "MATCH (u:User)\nWHERE u.dontreqpreauth = true\nAND u.enabled = true\nRETURN u\nLIMIT 100", + "query": "MATCH p = (s:Base)-[:GenericAll|GenericWrite|Owns|WriteOwner|WriteDacl]->(:IssuancePolicy)\nWHERE NOT s.objectid ENDS WITH '-512' AND NOT s.objectid ENDS WITH '-519'\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [ - "https://attack.mitre.org/techniques/T1558/004/" - ], + "resources": [], "acknowledgements": [] }, { - "name": "Dangerous privileges for Domain Users groups", - "guid": "9b8b9c18-f8c6-4c54-a20f-de0f7a7edbe0", + "name": "Shortest paths to systems trusted for unconstrained delegation", + "guid": "16a9e47b-45f8-4514-b409-771bb5186142", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Shortest Paths", "description": null, - "query": "MATCH p=(s:Group)-[:AD_ATTACK_PATHS]->(:Base)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", + "query": "MATCH p=shortestPath((s)-[:AD_ATTACK_PATHS*1..]->(t:Computer))\nWHERE t.unconstraineddelegation = true AND s<>t\nRETURN p\nLIMIT 1000", "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "All Operators", - "guid": "3dfd0843-1ff9-4c21-aa67-feae08d109de", + "name": "Enrollment rights on published ESC2 certificate templates", + "guid": "ebc77984-1ceb-4ed2-a395-ce1067847941", + "prebuilt": true, + "platforms": [ + "Active Directory" + ], + "category": "Active Directory Certificate Services", + "description": null, + "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(c:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)\nWHERE c.requiresmanagerapproval = false\nAND (c.effectiveekus = [''] OR '2.5.29.37.0' IN c.effectiveekus OR c.effectiveekus IS NULL)\nAND (c.authorizedsignatures = 0 OR c.schemaversion = 1)\nRETURN p\nLIMIT 1000", + "revision": 2, + "resources": [ + "https://posts.specterops.io/certified-pre-owned-d95910965cd2", + "https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-2-ac7f925d1547" + ], + "acknowledgements": [] + }, + { + "name": "Large default group added to computer-local group", + "guid": "dde133d2-b4d2-4de9-a656-905f3bf066f3", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(:Base)-[:MemberOf]->(n:Group)\nWHERE (\n n.objectid ENDS WITH 'S-1-5-32-551' OR // Backup Operators\n n.objectid ENDS WITH 'S-1-5-32-556' OR // Network Configuration Operators\n n.objectid ENDS WITH 'S-1-5-32-549' OR // Server Operators\n n.objectid ENDS WITH 'S-1-5-32-579' OR // Access Control Assistance Operators\n n.objectid ENDS WITH 'S-1-5-32-548' OR // Account Operators\n n.objectid ENDS WITH 'S-1-5-32-569' OR // Cryptographic Operators\n n.objectid ENDS WITH 'S-1-5-32-550' // Print Operators\n)\nRETURN p", + "query": "MATCH p=(n:Group)-[:MemberOfLocalGroup]->(m:ADLocalGroup)-[:LocalToComputer]->(:Computer)\nWHERE n.objectid =~ \".*-(S-1-5-11|S-1-1-0|S-1-5-32-545|S-1-5-7|-513|-515)$\" // Authenticated Users, Everyone, Users, Anonymous, Domain Users, Domain Computers\nAND NOT m.objectid =~ \".*-(545|574|554)$\" // Users, Certificate Service DCOM Access, Pre-Windows 2000 Compatible Access\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -2325,85 +2366,91 @@ ] }, { - "name": "Accounts with SID History", - "guid": "8172d52c-a975-49bd-9180-5b6efc59c9ab", - "prebuilt": false, + "name": "Locations of Tier Zero / High Value objects", + "guid": "18a83a17-b451-4343-acfe-7620516e2968", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Domain Information", "description": null, - "query": "MATCH p=(:Base)-[:HasSIDHistory]->(:Base)\nRETURN p", + "query": "MATCH p = (t:Base)<-[:Contains*1..]-(:Domain)\nWHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Circular AD group memberships", - "guid": "fcaa5ffc-3d22-481f-a2a2-18a4eec30058", - "prebuilt": false, + "name": "Tier Zero / High Value external Entra ID users", + "guid": "20e07417-d286-4dca-a962-568f2b262f65", + "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Active Directory Hygiene", - "description": "Detects circular group membership chains where groups are members of themselves through one or more intermediate groups. This causes an administrative complexity.", - "query": "MATCH p=(x:Group)-[:MemberOf*2..]->(y:Group)\nWHERE x.objectid=y.objectid\nRETURN p\nLIMIT 100", + "category": "Azure Hygiene", + "description": null, + "query": "MATCH (n:AZUser)\nWHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND n.name CONTAINS '#EXT#@'\nRETURN n\nLIMIT 100", + "revision": 1, + "resources": [], + "acknowledgements": [] + }, + { + "name": "Non-Tier Zero principals with BadSuccessor rights (with prerequisites check)", + "guid": "74daaebe-6040-4f7a-9c9a-416faf73dcc3", + "prebuilt": false, + "platforms": [ + "Active Directory" + ], + "category": "Dangerous Privileges", + "description": "Finds non-Tier Zero principals with BadSuccessor rights after checking prerequisites check (DC2025 & KDC key).", + "query": "// Find 2025 DCs\nMATCH (dc:Computer)\nWHERE dc.isdc = true AND dc.operatingsystem CONTAINS '2025'\n// Find gMSAs\nMATCH (m:User)\nWHERE m.gmsa = true\n// Find OU control\nMATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base)\n// Confirm domain has a 2025 DC\nWHERE ou.domain = dc.domain\n// Confirm domain KDC key\nAND ou.domain = m.domain\n// Exclude Tier Zero\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p LIMIT 1000", "revision": 1, "resources": [ - "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" + "https://bsky.app/profile/specterops.io/post/3lpua65qeu22l" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Foreign Service Principals With Group Memberships", - "guid": "327ef6a5-bfa8-4c92-b35a-d3df85264a24", - "prebuilt": false, + "name": "Shortest paths to privileged roles", + "guid": "3dc73dd8-4873-4aeb-a88f-56a58c77f512", + "prebuilt": true, "platforms": [ "Azure" ], - "category": "Azure Hygiene", - "description": "Review each to validate whether their presence is expected and whether the assigned group memberships are appropriate for the foreign service principal.", - "query": "MATCH p = (sp:AZServicePrincipal)-[:AZMemberOf]->(g:AZGroup)\nWHERE toUpper(sp.appownerorganizationid) <> toUpper(g.tenantid)\n// Ensure AZServicePrincipal has a valid appownerorganizationid\nAND sp.appownerorganizationid CONTAINS \"-\"\nRETURN p\nLIMIT 1000", - "revision": 1, - "resources": [ - "https://posts.specterops.io/microsoft-breach-how-can-i-see-this-in-bloodhound-33c92dca4c65" - ], - "acknowledgements": [ - "Stephen Hinck" - ] + "category": "Shortest Paths", + "description": null, + "query": "MATCH p=shortestPath((s:AZBase)-[:AZ_ATTACK_PATHS*1..]->(t:AZRole))\nWHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator' AND s<>t\nRETURN p\nLIMIT 1000", + "revision": 3, + "resources": [], + "acknowledgements": [] }, { - "name": "Direct Principal Rights Assignment", - "guid": "1d9c6ae3-38fc-4089-b5ad-fc3be0fa8eec", - "prebuilt": false, + "name": "All Kerberoastable users", + "guid": "14ab4eaa-b73b-49c4-b2d1-1e020757c995", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "This query identifies rights assigned directly to users or computers instead of groups. Active Directory best practice requires granting rights to groups, then adding users as group members. This role-based access control (RBAC) approach ensures permissions are easily auditable and manageable. Results include inherited rights, which must be modified at the parent container level.", - "query": "MATCH p=(n:Base)-[r:GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13]->(:Base)\nWHERE (n:User OR n:Computer) \nRETURN p\nLIMIT 1000", + "category": "Kerberos Interaction", + "description": null, + "query": "MATCH (u:User)\nWHERE u.hasspn=true\nAND u.enabled = true\nAND NOT u.objectid ENDS WITH '-502'\nAND NOT COALESCE(u.gmsa, false) = true\nAND NOT COALESCE(u.msa, false) = true\nRETURN u\nLIMIT 100", "revision": 1, "resources": [ - "https://softwareengineering.stackexchange.com/questions/11856/whats-wrong-with-circular-references" + "https://attack.mitre.org/techniques/T1558/003/" ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Tier Zero computers with the WebClient running", - "guid": "27a6f917-8ed4-4e2e-9b38-41a4b6de1b14", + "name": "All DNSAdmins", + "guid": "183fb320-f3ae-4ab3-a090-3f9a7db692e1", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Domain Information", "description": null, - "query": "MATCH (c:Computer)\nWHERE c.webclientrunning = True\nAND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN c LIMIT 1000", + "query": "MATCH p=(n:Base)-[:MemberOf]->(g:Group) \nWHERE n.name STARTS WITH \"DNSADMINS@\"\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -2411,131 +2458,107 @@ ] }, { - "name": "Principals with DCSync privileges", - "guid": "6e9beb8a-ad14-43de-bda1-644d174a5906", + "name": "Devices with unsupported operating systems", + "guid": "e3f2b53a-7ce6-4e52-9c74-68b69338288b", "prebuilt": true, "platforms": [ - "Active Directory" + "Azure" ], - "category": "Dangerous Privileges", + "category": "Azure Hygiene", "description": null, - "query": "MATCH p=(:Base)-[:DCSync|AllExtendedRights|GenericAll]->(:Domain)\nRETURN p\nLIMIT 1000", + "query": "MATCH (n:AZDevice)\nWHERE n.operatingsystem CONTAINS 'WINDOWS'\nAND n.operatingsystemversion =~ '(10.0.19044|10.0.22000|10.0.19043|10.0.19042|10.0.19041|10.0.18363|10.0.18362|10.0.17763|10.0.17134|10.0.16299|10.0.15063|10.0.14393|10.0.10586|10.0.10240|6.3.9600|6.2.9200|6.1.7601|6.0.6200|5.1.2600|6.0.6003|5.2.3790|5.0.2195).?.*'\nRETURN n\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "ESC8-vulnerable Enterprise CAs", - "guid": "60881923-296c-4702-adf7-a4f059dc9bb8", + "name": "Workstations where Domain Users can RDP", + "guid": "9486e0e6-2617-4595-b969-cf57ca21fc86", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "NTLM Relay Attacks", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (n:EnterpriseCA)\nWHERE n.hasvulnerableendpoint=true\nRETURN n", + "query": "MATCH p=(s:Group)-[:CanRDP]->(t:Computer)\nWHERE s.objectid ENDS WITH '-513' AND NOT toUpper(t.operatingsystem) CONTAINS 'SERVER'\nRETURN p\nLIMIT 1000", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Entra ID SSO accounts not rolling Kerberos decryption key", - "guid": "1867abf8-08e3-4ea8-8f65-8366079d35c4", - "prebuilt": false, - "platforms": [ - "Active Directory", - "Azure" - ], - "category": "Configuration Weakness", - "description": "Microsoft highly recommends that you roll over the Entra ID SSO Kerberos decryption key at least every 30 days.", - "query": "MATCH (n:Computer)\nWHERE n.name STARTS WITH \"AZUREADSSOACC.\"\nAND n.pwdlastset < (datetime().epochseconds - (30 * 86400))\nRETURN n", - "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-faq#how-can-i-roll-over-the-kerberos-decryption-key-of-the--azureadsso--computer-account-" - ], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] - }, - { - "name": "Sessions across trusts", - "guid": "aea7ac64-1f51-407b-b0ee-19fd30075794", + "name": "Tier Zero computers not owned by Tier Zero", + "guid": "99d29ded-223a-442b-a0e0-f8b5694c6441", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "Users logging on across a trust, the users originate from trusted domains.", - "query": "MATCH p=(trustedDomainPrincipal:Computer)-[r:HasSession]->(trustingDomainPrincipal:User)\nWHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid\nRETURN p\nLIMIT 1000", - "revision": 1, + "category": "Dangerous Privileges", + "description": null, + "query": "MATCH p=(n:Base)-[:Owns]->(:Computer)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", + "revision": 2, "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Domains not mitigating CVE-2021-42291", - "guid": "02202726-d86d-46c2-891c-9770c635f76f", + "name": "Uncommon permission on containers", + "guid": "018c2b45-e30f-47d8-a751-22419c3d0736", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "Checks the AttributeAuthorizationOnLDAPAdd flag of dSHeuristics.", - "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \"^(.{0,27}|.{27}[^1].*)$\"\nRETURN n", + "description": "BloodHound typically identifies risk on Active Directory objects stored in OUs, however behind the scenes; Active Directory has a hieracy of containers e.g. CN=SYSTEM and CN=CONFIGURATION, on which control can lead to risk. Results are prone to false-positives but can assist auditing containers permissions.", + "query": "MATCH p=(:Domain)-[:Contains*1..]->(c:Container)<-[r]-(n:Base)\n\n// Exclude Tier Zero\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\n\n// Scope edges to ACLs\nAND r.isacl\n\n// Exclude CN=Users and CN=Computers containers\nAND NOT c.distinguishedname STARTS WITH \"CN=COMPUTERS,DC=\"\nAND NOT c.distinguishedname STARTS WITH \"CN=USERS,DC=\"\n\n// Exclude same-domain unresolved SIDs\nAND NOT (n.distinguishedname IS NULL AND n.domainsid = c.domainsid)\n\n// Exclude default: Cert Publishers\nAND NOT (c.distinguishedname CONTAINS \",CN=PUBLIC KEY SERVICES,CN=SERVICES,CN=CONFIGURATION,DC=\" AND n.objectid ENDS WITH \"-517\")\n\n// Exclude default: RAS and IAS Servers\nAND NOT (c.distinguishedname CONTAINS \"CN=RAS AND IAS SERVERS ACCESS CHECK,CN=SYSTEM,DC=\" AND n.objectid ENDS WITH \"-553\")\n\n// Exclude default: DNS\nAND NOT (c.distinguishedname CONTAINS \"CN=MICROSOFTDNS,CN=SYSTEM,DC=\" AND n.name STARTS WITH \"DNSADMINS@\")\n\n// Exclude default: ConfigMgr\nAND NOT (c.distinguishedname STARTS WITH \"CN=SYSTEM MANAGEMENT,CN=SYSTEM,DC=\" AND n.samaccountname ENDS WITH \"$\")\n\n// Exclude default: Exchange pt1\nAND NOT (c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\" AND (n.name STARTS WITH \"EXCHANGE TRUSTED SUBSYSTEM@\" OR n.name STARTS WITH \"ORGANIZATION MANAGEMENT@\" OR n.name STARTS WITH \"EXCHANGE SERVICES@\"))\n\n// Exclude default: Exchange pt2\nAND NOT ((c.distinguishedname CONTAINS \"CN=MONITORING MAILBOXES,CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\" OR c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\") AND n.name STARTS WITH \"EXCHANGE ENTERPRISE SERVERS@\")\n\n// Exclude default: Exchange pt3\nAND NOT ((c.distinguishedname CONTAINS \"CN=ACTIVE DIRECTORY CONNECTIONS,CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\" OR c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\" OR c.distinguishedname =~ \"CN=RECIPIENT UPDATE SERVICES,CN=ADDRESS LISTS CONTAINER,CN=.*,CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\") AND n.name STARTS WITH \"EXCHANGE DOMAIN SERVERS@\")\n\nRETURN p\nLIMIT 2000", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "All coerce and NTLM relay edges", - "guid": "15c5ff3b-856c-44d1-a731-a8cb72512dd1", + "name": "Computers with the WebClient running", + "guid": "51107ad1-f0bc-43d3-a561-5cee471ca196", "prebuilt": true, "platforms": [ "Active Directory" ], "category": "NTLM Relay Attacks", "description": null, - "query": "MATCH p = (n:Base)-[:CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|CoerceAndRelayNTLMToADCS|CoerceAndRelayNTLMToSMB]->(:Base)\nRETURN p LIMIT 500", + "query": "MATCH (c:Computer)\nWHERE c.webclientrunning = True\nRETURN c LIMIT 1000", "revision": 1, - "resources": [ - "https://specterops.io/blog/2025/04/08/the-renaissance-of-ntlm-relay-attacks-everything-you-need-to-know/" - ], + "resources": [], "acknowledgements": [] }, { - "name": "Overprivileged Microsoft Entra Connect accounts", - "guid": "9e6e75b4-9ecc-45d4-a39b-b6427b813f0a", + "name": "Collection health of CA Registry Data", + "guid": "c8dd3479-8063-450a-9456-557bc5f39e10", "prebuilt": false, "platforms": [ - "Active Directory", - "Azure" + "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "Legacy MSOL accounts were by default deployed with Domain Admins or Enterprise Admins membership.", - "query": "MATCH p=(n:User)-[:MemberOf*1..]->(g:Group)\nWHERE n.name STARTS WITH \"MSOL_\"\nAND (g.objectid ENDS WITH \"-512\" // Domain Admins\nOR g.objectid ENDS WITH \"-519\") // Entterprise Admins\nRETURN p", + "category": "Domain Information", + "description": "BloodHound's ADCS analysis requires collecting CA registry data to increase accuracy/enable more edges. Collection by default requires SharpHound has Administrators membership. Requires SharpHound v2.3.5 or above. It only requires one misconfigured CA to potentially a full forest compromise by any principal. CAs returned by this query have not been collected.", + "query": "MATCH p=(eca:EnterpriseCA)<-[:HostsCAService]-(c:Computer)\nWHERE (\n eca.isuserspecifiessanenabledcollected = false\n OR eca.casecuritycollected = false\n OR eca.enrollmentagentrestrictionscollected = false\n OR eca.roleseparationenabledcollected = false\n)\n// Exclude inactive CAs\nAND c.enabled = true\nAND c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400))\nRETURN p", "revision": 1, "resources": [ - "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/reference-connect-accounts-permissions" + "https://bloodhound.specterops.io/collect-data/enterprise-collection/permissions#ca-registry" ], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Non-Tier Zero account with unconstrained delegation", - "guid": "e7e9a927-3f34-42c7-b921-d8bcf626011e", + "name": "Non-Tier Zero accounts with SID History of Tier Zero accounts", + "guid": "59744dfe-9411-4daf-b342-1203dc62acd4", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Dangerous Privileges", "description": null, - "query": "MATCH (n:Base)\nWHERE n.unconstraineddelegation = true\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN n", + "query": "MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0')\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -2543,61 +2566,45 @@ ] }, { - "name": "Computers with membership in Protected Users", - "guid": "a26372f4-2e92-49f6-8993-6657fbc1569a", - "prebuilt": true, - "platforms": [ - "Active Directory" - ], - "category": "NTLM Relay Attacks", - "description": null, - "query": "MATCH p = (:Base)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectid ENDS WITH \"-525\"\nRETURN p LIMIT 1000", - "revision": 1, - "resources": [], - "acknowledgements": [] - }, - { - "name": "Non-Tier Zero principals with control of AdminSDHolder", - "guid": "4c1e0137-5b7f-48d8-bd09-9db7674bca61", + "name": "Accounts with SID History to a non-existent domain", + "guid": "2710401a-c4c2-4d2c-9edb-d7625045f2e8", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Dangerous Privileges", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Group)-[r:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteOwnerLimitedRights|OwnsLimitedRights]->(m:Container)\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nAND m.name STARTS WITH \"ADMINSDHOLDER@\"\nRETURN p", + "query": "MATCH (d:Domain)\nWITH collect(d.objectid) AS domainSIDs\nMATCH p=(n:Base)-[:HasSIDHistory]->(m:Base)\nWHERE NOT n.domainsid IN domainSIDs\nRETURN p", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory#adminsdholder" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Enrollment rights on CertTemplates with OIDGroupLink", - "guid": "140a68eb-d21c-4b75-971f-309225fb2d75", + "name": "Tier Zero / High Value enabled users not requiring smart card authentication", + "guid": "867f9f17-c149-4c4b-ad84-9a807622ff8c", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Certificate Services", + "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:ExtendedByPolicy]->(:IssuancePolicy)-[:OIDGroupLink]->(:Group)\nRETURN p\nLIMIT 1000", + "query": "MATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0')\nAND u.enabled = true\nAND u.smartcardrequired = false\nAND NOT u.name STARTS WITH 'MSOL_' // Removes false positive, Entra sync\nAND NOT u.name STARTS WITH 'PROVAGENTGMSA' // Removes false positive, Entra sync\nAND NOT u.name STARTS WITH 'ADSYNCMSA_' // Removes false positive, Entra sync\nRETURN u", "revision": 1, "resources": [], "acknowledgements": [] }, { - "name": "Non-default members in Pre-Windows 2000 Compatible Access", - "guid": "091995b9-7254-473a-996f-6b8368d20431", + "name": "Tier Zero computers with unsupported operating systems", + "guid": "a87b558c-5746-4a90-9f83-c86e7b924a52", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", "description": null, - "query": "MATCH p=(n:Group)-[:MemberOf]->(m:Group)\nWHERE NOT n.objectid ENDS WITH \"S-1-5-11\" // Authenticated Users\nAND NOT (n.objectid ENDS WITH \"S-1-5-7\" // Anonymous\nAND NOT n.objectid ENDS WITH \"S-1-1-0\") // Everyone\nAND m.objectid ENDS WITH \"S-1-5-32-554\" // Pre-Windows 2000 Compatible Access\nRETURN p", + "query": "MATCH (c:Computer)\nWHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*'\nAND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN c\nLIMIT 100", "revision": 1, "resources": [], "acknowledgements": [ @@ -2605,62 +2612,57 @@ ] }, { - "name": "All incoming and local paths for a specific computer", - "guid": "1f67e538-19d4-4020-89c8-5b39b31571bd", - "prebuilt": false, + "name": "Tier Zero / High Value users with non-expiring passwords", + "guid": "4eca1b69-00a2-48a0-abb3-b94ea647cf6b", + "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Domain Information", - "description": "All incoming and local paths for a specific computer; incoming from domain objects and paths local inside the computer.", - "query": "// Replace 'HOSTNAME' with the computer's shortname eg. 'SRV01', not FQDN\nMATCH p=(n:Base)-[:RemoteInteractiveLogonPrivilege|AdminTo|CanRDP|LocalToComputer|MemberOfLocalGroup]-(m:Base)\nWHERE m.name CONTAINS 'HOSTNAME'\nAND m.name CONTAINS '.' // Only see computer-related objects (eg. not AD Groups)\nRETURN p", + "category": "Active Directory Hygiene", + "description": null, + "query": "MATCH (u:User)\nWHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0') AND u.enabled = true\nAND u.pwdneverexpires = true\nRETURN u\nLIMIT 100", "revision": 1, "resources": [], - "acknowledgements": [ - "Martin Sohn Christensen, @martinsohndk" - ] + "acknowledgements": [] }, { - "name": "Entra Users synced from On-Prem Users added to Domain Admins group", - "guid": "62722d5f-bd93-4d11-beeb-9be261827e4e", + "name": "All members of high privileged roles", + "guid": "3df24d92-dd12-4125-811b-e696b098f60e", "prebuilt": true, "platforms": [ - "Active Directory", "Azure" ], - "category": "Cross Platform Attack Paths", + "category": "General", "description": null, - "query": "MATCH p = (:AZUser)-[:SyncedToADUser]->(:User)-[:MemberOf]->(t:Group)\nWHERE t.objectid ENDS WITH '-512'\nRETURN p\nLIMIT 1000", - "revision": 1, + "query": "MATCH p=(t:AZRole)<-[:AZHasRole|AZMemberOf*1..2]-(:AZBase)\nWHERE t.name =~ '(?i)Global Administrator|User Administrator|Cloud Application Administrator|Authentication Policy Administrator|Exchange Administrator|Helpdesk Administrator|Privileged Authentication Administrator|Privileged Role Administrator'\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [] }, { - "name": "Kerberoastable users with most admin privileges", - "guid": "9907b208-494c-4ba6-846d-485e6de14e17", + "name": "Computers where Domain Users can read LAPS passwords", + "guid": "aa4bfa95-e7b9-4d56-8f35-f34f04d7b6f4", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Kerberos Interaction", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH (u:User)\nWHERE u.hasspn = true\n AND u.enabled = true\n AND NOT u.objectid ENDS WITH '-502'\n AND NOT COALESCE(u.gmsa, false) = true\n AND NOT COALESCE(u.msa, false) = true\nMATCH (u)-[:MemberOf|AdminTo*1..]->(c:Computer)\nWITH DISTINCT u, COUNT(c) AS adminCount\nRETURN u\nORDER BY adminCount DESC\nLIMIT 100", + "query": "MATCH p=(s:Group)-[:AllExtendedRights|ReadLAPSPassword]->(:Computer)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", "revision": 1, - "resources": [ - "https://attack.mitre.org/techniques/T1558/003/" - ], + "resources": [], "acknowledgements": [] }, { - "name": "Uncommon permission on containers", - "guid": "018c2b45-e30f-47d8-a751-22419c3d0736", + "name": "Domains affected by AdPrep privilege escalation risk", + "guid": "815ff190-f6f3-4757-a516-2f4bf589b705", "prebuilt": false, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", - "description": "BloodHound typically identifies risk on Active Directory objects stored in OUs, however behind the scenes; Active Directory has a hieracy of containers e.g. CN=SYSTEM and CN=CONFIGURATION, on which control can lead to risk. Results are prone to false-positives but can assist auditing containers permissions.", - "query": "MATCH p=(:Domain)-[:Contains*1..]->(c:Container)<-[r]-(n:Base)\n\n// Exclude Tier Zero\nWHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\n\n// Scope edges to ACLs\nAND r.isacl\n\n// Exclude CN=Users and CN=Computers containers\nAND NOT c.distinguishedname STARTS WITH \"CN=COMPUTERS,DC=\"\nAND NOT c.distinguishedname STARTS WITH \"CN=USERS,DC=\"\n\n// Exclude same-domain unresolved SIDs\nAND NOT (n.distinguishedname IS NULL AND n.domainsid = c.domainsid)\n\n// Exclude default: Cert Publishers\nAND NOT (c.distinguishedname CONTAINS \",CN=PUBLIC KEY SERVICES,CN=SERVICES,CN=CONFIGURATION,DC=\" AND n.objectid ENDS WITH \"-517\")\n\n// Exclude default: RAS and IAS Servers\nAND NOT (c.distinguishedname CONTAINS \"CN=RAS AND IAS SERVERS ACCESS CHECK,CN=SYSTEM,DC=\" AND n.objectid ENDS WITH \"-553\")\n\n// Exclude default: DNS\nAND NOT (c.distinguishedname CONTAINS \"CN=MICROSOFTDNS,CN=SYSTEM,DC=\" AND n.name STARTS WITH \"DNSADMINS@\")\n\n// Exclude default: ConfigMgr\nAND NOT (c.distinguishedname STARTS WITH \"CN=SYSTEM MANAGEMENT,CN=SYSTEM,DC=\" AND n.samaccountname ENDS WITH \"$\")\n\n// Exclude default: Exchange pt1\nAND NOT (c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\" AND (n.name STARTS WITH \"EXCHANGE TRUSTED SUBSYSTEM@\" OR n.name STARTS WITH \"ORGANIZATION MANAGEMENT@\" OR n.name STARTS WITH \"EXCHANGE SERVICES@\"))\n\n// Exclude default: Exchange pt2\nAND NOT ((c.distinguishedname CONTAINS \"CN=MONITORING MAILBOXES,CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\" OR c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\") AND n.name STARTS WITH \"EXCHANGE ENTERPRISE SERVERS@\")\n\n// Exclude default: Exchange pt3\nAND NOT ((c.distinguishedname CONTAINS \"CN=ACTIVE DIRECTORY CONNECTIONS,CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\" OR c.distinguishedname CONTAINS \"CN=MICROSOFT EXCHANGE SYSTEM OBJECTS,DC=\" OR c.distinguishedname =~ \"CN=RECIPIENT UPDATE SERVICES,CN=ADDRESS LISTS CONTAINER,CN=.*,CN=MICROSOFT EXCHANGE,CN=SERVICES,CN=CONFIGURATION,DC=\") AND n.name STARTS WITH \"EXCHANGE DOMAIN SERVERS@\")\n\nRETURN p\nLIMIT 2000", + "category": "Dangerous Privileges", + "description": null, + "query": "MATCH p=(n:Group)-[r:GenericAll]->(m:Domain)\nWHERE n.objectid ENDS WITH \"-527\" // Enterprise Key Admins\nAND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0')\nRETURN p", "revision": 1, "resources": [], "acknowledgements": [ @@ -2668,34 +2670,32 @@ ] }, { - "name": "Domains allowing unauthenticated NSPI RPC binds", - "guid": "a950fdab-5934-4c69-a88b-e2e0e3da9d52", + "name": "Smart card accounts with passwords not rotated in over 1 year", + "guid": "7e56f2e7-79c3-4f0d-aa3e-14cf3de7ab73", "prebuilt": false, "platforms": [ "Active Directory" ], "category": "Active Directory Hygiene", - "description": "Checks the fAllowAnonNSPI flag of dSHeuristics.", - "query": "MATCH (n:Domain)\nWHERE n.dsheuristics =~ \".{7}[^0].*\"\nRETURN n", + "description": null, + "query": "MATCH (n:Base)\nWHERE n.pwdlastset < (datetime().epochseconds - (365 * 86400))\nAND n.enabled = true\nAND n.smartcardrequired = true\nRETURN n", "revision": 1, - "resources": [ - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5" - ], + "resources": [], "acknowledgements": [ "Martin Sohn Christensen, @martinsohndk" ] }, { - "name": "Cross-forest trusts with abusable configuration", - "guid": "5cf1f354-80d4-420e-bc4b-424fabc21a56", + "name": "Dangerous privileges for Domain Users groups", + "guid": "9b8b9c18-f8c6-4c54-a20f-de0f7a7edbe0", "prebuilt": true, "platforms": [ "Active Directory" ], - "category": "Active Directory Hygiene", + "category": "Dangerous Privileges", "description": null, - "query": "MATCH p=(n:Domain)-[:CrossForestTrust|SpoofSIDHistory|AbuseTGTDelegation]-(m:Domain)\nWHERE (n)-[:SpoofSIDHistory|AbuseTGTDelegation]-(m)\nRETURN p", - "revision": 1, + "query": "MATCH p=(s:Group)-[:AD_ATTACK_PATHS]->(:Base)\nWHERE s.objectid ENDS WITH '-513'\nRETURN p\nLIMIT 1000", + "revision": 2, "resources": [], "acknowledgements": [] }