From 30def278243c60c9811b74464eeeafd81d380628 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 11 Jun 2025 16:48:49 +0100 Subject: [PATCH 1/3] readme minor fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index aab59b2..9ea7620 100644 --- a/README.md +++ b/README.md @@ -40,10 +40,10 @@ One of BloodHound’s key features is its flexibility through Cypher queries – Queries can answer anything from simple questions (e.g., “*Which users haven’t reset their passwords in 180 days?*”), to complex identity attack path problems (e.g., “*Which low-privileged users can compromise computers hosting a gMSA with unconstrained delegation?*”). -The library gives you practical examples for learning Cypher and can be combined with the following resources: +The library gives you practical examples for learning Cypher and can be combined with these resources: - [BloodHound documentation: Searching with Cypher](https://support.bloodhoundenterprise.io/hc/en-us/articles/16721164740251) - [openCypher resources](https://opencypher.org/resources/) -- [Neo4j Cypher Cheat Sheet](https://opencypher.org/resources/) +- [Neo4j Cypher Cheat Sheet](https://neo4j.com/docs/cypher-cheat-sheet/current/lists/) You can also learn with the communty by joining the #cypher_queries channel in the [BloodHound community Slack](https://support.bloodhoundenterprise.io/hc/en-us/articles/16730536907547). From f5f4d266cc8cd7e21300ac8bd7b684a2c6f51c79 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 12 Jun 2025 10:21:04 +0100 Subject: [PATCH 2/3] delete old query structure --- ...SDHolder protected Accounts and Groups.yml | 20 ------------------- .../Trusts/Sessions across trusts.yml | 15 -------------- .../Map Azure Management structure.yml | 13 ------------ 3 files changed, 48 deletions(-) delete mode 100644 Queries/Active Directory/Domain Information/AdminSDHolder protected Accounts and Groups.yml delete mode 100644 Queries/Active Directory/Trusts/Sessions across trusts.yml delete mode 100644 Queries/Azure/General/Map Azure Management structure.yml diff --git a/Queries/Active Directory/Domain Information/AdminSDHolder protected Accounts and Groups.yml b/Queries/Active Directory/Domain Information/AdminSDHolder protected Accounts and Groups.yml deleted file mode 100644 index 3cd19a1..0000000 --- a/Queries/Active Directory/Domain Information/AdminSDHolder protected Accounts and Groups.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: AdminSDHolder protected Accounts and Groups -guid: 5ee2f40e-a55c-4140-ab8a-91746ba3752b -platform: 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) - WHERE ( - 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 - 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 - OR n.objectid =~ ".*-(500|502|516|521)" // Direct objects - ) - RETURN n -note: -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 -acknowledgement: - diff --git a/Queries/Active Directory/Trusts/Sessions across trusts.yml b/Queries/Active Directory/Trusts/Sessions across trusts.yml deleted file mode 100644 index c8366c9..0000000 --- a/Queries/Active Directory/Trusts/Sessions across trusts.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Sessions across trusts -guid: aea7ac64-1f51-407b-b0ee-19fd30075794 -platform: Active Directory -category: Trusts -description: Users logging on across a trust, the users originate from trusted domains. -query: |- - MATCH p=(trustedDomainPrincipal:Computer)-[r:HasSession]->(trustingDomainPrincipal:User) - WHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid - RETURN p - LIMIT 1000 -note: -revision: 1 -resources: -acknowledgement: - diff --git a/Queries/Azure/General/Map Azure Management structure.yml b/Queries/Azure/General/Map Azure Management structure.yml deleted file mode 100644 index ab403ea..0000000 --- a/Queries/Azure/General/Map Azure Management structure.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Map Azure Management structure -guid: c1bb109e-e6a4-4c91-864f-f78e1e42615e -platform: Azure -category: General -description: Maps the structure of Azure Management -query: |- - MATCH p = (:AZTenant)-[:AZContains*1..]->(:AZResourceGroup) - RETURN p - LIMIT 1000 -note: -revision: 1 -resources: https://learn.microsoft.com/en-us/azure/governance/management-groups/overview -acknowledgement: Martin Sohn Christensen, @martinsohndk \ No newline at end of file From 216543a80342fe0686ae9b5e0589243481cfaa46 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 12 Jun 2025 11:09:22 +0100 Subject: [PATCH 3/3] initial query commit --- queries/ACEs across trusts.yml | 18 +++++++++++ ...table Tier Zero users (DontReqPreAuth).yml | 16 ++++++++++ ...S-REP Roastable users (DontReqPreAuth).yml | 17 +++++++++++ ...h SID History to a non-existent domain.yml | 17 +++++++++++ ...h SID History to a same-domain account.yml | 15 ++++++++++ queries/Accounts with SID History.yml | 14 +++++++++ ...ts with clear-text password attributes.yml | 18 +++++++++++ ...SDHolder protected Accounts and Groups.yml | 22 ++++++++++++++ ...ll ADCS ESC privilege escalation edges.yml | 20 +++++++++++++ queries/All DNSAdmins.yml | 15 ++++++++++ queries/All Domain Admins.yml | 16 ++++++++++ queries/All Global Administrators.yml | 15 ++++++++++ queries/All Kerberoastable users.yml | 20 +++++++++++++ queries/All Operator groups.yml | 23 ++++++++++++++ queries/All Schema Admins.yml | 16 ++++++++++ queries/All coerce and NTLM relay edges.yml | 14 +++++++++ ...nd local paths for a specific computer.yml | 18 +++++++++++ .../All members of high privileged roles.yml | 16 ++++++++++ .../All paths crossing a specific trust.yml | 20 +++++++++++++ ...h Microsoft Graph App Role assignments.yml | 15 ++++++++++ ...privilege to grant arbitrary App Roles.yml | 15 ++++++++++ queries/CA administrators and CA managers.yml | 15 ++++++++++ ...r owners who can obtain LAPS passwords.yml | 15 ++++++++++ ...ters not requiring inbound SMB signing.yml | 15 ++++++++++ ... Domain Users are local administrators.yml | 16 ++++++++++ ...e Domain Users can read LAPS passwords.yml | 16 ++++++++++ ...ers with membership in Protected Users.yml | 15 ++++++++++ ...h non-default Primary Group membership.yml | 18 +++++++++++ ... than the default maximum password age.yml | 20 +++++++++++++ .../Computers with the WebClient running.yml | 15 ++++++++++ ... outgoing NTLM setting set to Deny all.yml | 15 ++++++++++ ...ers with unsupported operating systems.yml | 16 ++++++++++ ...est trusts with abusable configuration.yml | 15 ++++++++++ ...lnerable to NTLM relay to LDAP attacks.yml | 17 +++++++++++ ...ous privileges for Domain Users groups.yml | 16 ++++++++++ ...ces with unsupported operating systems.yml | 17 +++++++++++ ...d Tier Zero High Value principals - AD.yml | 19 ++++++++++++ ...d Tier Zero High Value principals - AZ.yml | 17 +++++++++++ ...dmins logons to non-Domain Controllers.yml | 19 ++++++++++++ ...s allowing NTLMv1 or LM authentication.yml | 16 ++++++++++ ...s with UPN certificate mapping enabled.yml | 18 +++++++++++ ... with weak certificate binding enabled.yml | 16 ++++++++++ queries/Domain migration groups.yml | 15 ++++++++++ ...ed by AdPrep privilege escalation risk.yml | 16 ++++++++++ ... by Exchange privilege escalation risk.yml | 16 ++++++++++ ...owing authenticated domain enumeration.yml | 16 ++++++++++ ...llowing unauthenticated NSPI RPC binds.yml | 15 ++++++++++ ...ing unauthenticated domain enumeration.yml | 17 +++++++++++ ...thenticated rootDSE searches and binds.yml | 15 ++++++++++ ... groups from AdminSDHolder protections.yml | 15 ++++++++++ .../Domains not mitigating CVE-2021-42291.yml | 15 ++++++++++ ...s not verifying UPN and SPN uniqueness.yml | 15 ++++++++++ ...user can join a computer to the domain.yml | 17 +++++++++++ .../Domains with List Object mode enabled.yml | 15 ++++++++++ ... policy length less than 15 characters.yml | 15 ++++++++++ ...gle-point-of-failure Domain Controller.yml | 17 +++++++++++ ...unctional level not the latest version.yml | 15 ++++++++++ ...s with more than 50 Tier Zero accounts.yml | 17 +++++++++++ ... smart account passwords do not expire.yml | 17 +++++++++++ ...mains without Microsoft LAPS computers.yml | 18 +++++++++++ .../Domains without Protected Users group.yml | 20 +++++++++++++ ...ssword rotation on smart card accounts.yml | 17 +++++++++++ queries/ESC8-vulnerable Enterprise CAs.yml | 15 ++++++++++ ... Value principals inactive for 60 days.yml | 23 ++++++++++++++ .../Enabled built-in guest user accounts.yml | 16 ++++++++++ ... for 180 days - MSSQL Failover Cluster.yml | 24 +++++++++++++++ ...nabled computers inactive for 180 days.yml | 22 ++++++++++++++ .../Enabled users inactive for 180 days.yml | 21 +++++++++++++ ...hts on CertTemplates with OIDGroupLink.yml | 15 ++++++++++ ...ise CA with User Specified SAN enabled.yml | 16 ++++++++++ ...n published ESC1 certificate templates.yml | 19 ++++++++++++ ...n published ESC2 certificate templates.yml | 18 +++++++++++ ...e templates with no security extension.yml | 16 ++++++++++ ...hts on published certificate templates.yml | 15 ++++++++++ ...enrollment agent certificate templates.yml | 18 +++++++++++ ...ts not rolling Kerberos decryption key.yml | 18 +++++++++++ ...rem Users added to Domain Admins group.yml | 18 +++++++++++ ...cipals in Tier Zero High Value targets.yml | 18 +++++++++++ ...h passwords not rotated in over 1 year.yml | 18 +++++++++++ ...members of Tier Zero High Value groups.yml | 20 +++++++++++++ ...table users with most admin privileges.yml | 23 ++++++++++++++ ...count member of built-in Admins groups.yml | 20 +++++++++++++ ...ccounts without AES encryption support.yml | 24 +++++++++++++++ ...lt group added to computer-local group.yml | 16 ++++++++++ ...lt groups with outbound control of OUs.yml | 21 +++++++++++++ ...e default groups with outbound control.yml | 21 +++++++++++++ ...ations of Tier Zero High Value objects.yml | 16 ++++++++++ queries/Map Azure Management structure.yml | 16 ++++++++++ queries/Map OU structure.yml | 15 ++++++++++ queries/Map domain trusts.yml | 15 ++++++++++ ...llowed RODC Password Replication Group.yml | 16 ++++++++++ ...ted groups within Tier Zero High Value.yml | 18 +++++++++++ ...r Zero account with 'Admin Count' flag.yml | 16 ++++++++++ ...er Zero account with excessive control.yml | 20 +++++++++++++ ... account with unconstrained delegation.yml | 16 ++++++++++ ...with SID History of Tier Zero accounts.yml | 16 ++++++++++ ...cessor rights (no prerequisites check).yml | 18 +++++++++++ ...ssor rights (with prerequisites check).yml | 28 +++++++++++++++++ ...incipals with control of AdminSDHolder.yml | 16 ++++++++++ ...t delegation on MicrosoftDNS container.yml | 18 +++++++++++ ... in Pre-Windows 2000 Compatible Access.yml | 18 +++++++++++ ...lt permissions on IssuancePolicy nodes.yml | 16 ++++++++++ queries/Object name conflict.yml | 15 ++++++++++ ... to Entra Users that Own Entra Objects.yml | 17 +++++++++++ ...tra Users with Azure RM Roles (direct).yml | 17 +++++++++++ ... with Azure RM Roles (group delegated).yml | 17 +++++++++++ ... Users with Entra Admin Roles (direct).yml | 17 +++++++++++ ...th Entra Admin Roles (group delegated).yml | 17 +++++++++++ ...ntra Users with Entra Group Membership.yml | 17 +++++++++++ queries/PKI hierarchy.yml | 15 ++++++++++ ... Users to Tier Zero High Value targets.yml | 17 +++++++++++ queries/Principal with SPN keyword.yml | 18 +++++++++++ queries/Principals with DCSync privileges.yml | 15 ++++++++++ ... with DES-only Kerberos authentication.yml | 16 ++++++++++ ...s with foreign domain group membership.yml | 16 ++++++++++ ...rds stored using reversible encryption.yml | 15 ++++++++++ ...ak supported Kerberos encryption types.yml | 17 +++++++++++ queries/Public Key Services container.yml | 16 ++++++++++ .../Servers where Domain Users can RDP.yml | 16 ++++++++++ queries/Sessions across trusts.yml | 17 +++++++++++ ...ations to Tier Zero High Value targets.yml | 16 ++++++++++ ... Users to Tier Zero High Value targets.yml | 17 +++++++++++ ... Users to Tier Zero High Value targets.yml | 17 +++++++++++ ... paths from Owned objects to Tier Zero.yml | 18 +++++++++++ queries/Shortest paths from Owned objects.yml | 17 +++++++++++ .../Shortest paths to Azure Subscriptions.yml | 16 ++++++++++ ...omain Admins from Kerberoastable users.yml | 21 +++++++++++++ queries/Shortest paths to Domain Admins.yml | 16 ++++++++++ ... paths to Tier Zero High Value targets.yml | 16 ++++++++++ .../Shortest paths to privileged roles.yml | 16 ++++++++++ ...s trusted for unconstrained delegation.yml | 16 ++++++++++ ...h passwords not rotated in over 1 year.yml | 17 +++++++++++ ... principals synchronized with Entra ID.yml | 20 +++++++++++++ ...ot requiring smart card authentication.yml | 20 +++++++++++++ ...ero High Value external Entra ID users.yml | 17 +++++++++++ ...alue users with non-expiring passwords.yml | 17 +++++++++++ ...Denied RODC Password Replication Group.yml | 21 +++++++++++++ ...er Zero accounts that can be delegated.yml | 21 +++++++++++++ ...ters at risk of constrained delegation.yml | 15 ++++++++++ ... resource-based constrained delegation.yml | 15 ++++++++++ ... Zero computers not owned by Tier Zero.yml | 15 ++++++++++ ...ters not requiring inbound SMB signing.yml | 16 ++++++++++ ... than the default maximum password age.yml | 18 +++++++++++ ...o computers with the WebClient running.yml | 16 ++++++++++ ...ers with unsupported operating systems.yml | 17 +++++++++++ ...ro users not member of Protected Users.yml | 19 ++++++++++++ queries/Tier Zero users with email.yml | 30 +++++++++++++++++++ ...h passwords not rotated in over 1 year.yml | 19 ++++++++++++ queries/Trace ACE inheritance.yml | 19 ++++++++++++ .../Unresolved SID with outbound control.yml | 17 +++++++++++ ... built-in domain Administrator account.yml | 20 +++++++++++++ ...o not require password to authenticate.yml | 16 ++++++++++ ...gon scripts stored in a trusted domain.yml | 18 +++++++++++ ...h non-default Primary Group membership.yml | 19 ++++++++++++ queries/Users with non-expiring passwords.yml | 17 +++++++++++ ...h passwords not rotated in over 1 year.yml | 18 +++++++++++ ...orkstations where Domain Users can RDP.yml | 16 ++++++++++ 157 files changed, 2716 insertions(+) create mode 100644 queries/ACEs across trusts.yml create mode 100644 queries/AS-REP Roastable Tier Zero users (DontReqPreAuth).yml create mode 100644 queries/AS-REP Roastable users (DontReqPreAuth).yml create mode 100644 queries/Accounts with SID History to a non-existent domain.yml create mode 100644 queries/Accounts with SID History to a same-domain account.yml create mode 100644 queries/Accounts with SID History.yml create mode 100644 queries/Accounts with clear-text password attributes.yml create mode 100644 queries/AdminSDHolder protected Accounts and Groups.yml create mode 100644 queries/All ADCS ESC privilege escalation edges.yml create mode 100644 queries/All DNSAdmins.yml create mode 100644 queries/All Domain Admins.yml create mode 100644 queries/All Global Administrators.yml create mode 100644 queries/All Kerberoastable users.yml create mode 100644 queries/All Operator groups.yml create mode 100644 queries/All Schema Admins.yml create mode 100644 queries/All coerce and NTLM relay edges.yml create mode 100644 queries/All incoming and local paths for a specific computer.yml create mode 100644 queries/All members of high privileged roles.yml create mode 100644 queries/All paths crossing a specific trust.yml create mode 100644 queries/All service principals with Microsoft Graph App Role assignments.yml create mode 100644 queries/All service principals with Microsoft Graph privilege to grant arbitrary App Roles.yml create mode 100644 queries/CA administrators and CA managers.yml create mode 100644 queries/Computer owners who can obtain LAPS passwords.yml create mode 100644 queries/Computers not requiring inbound SMB signing.yml create mode 100644 queries/Computers where Domain Users are local administrators.yml create mode 100644 queries/Computers where Domain Users can read LAPS passwords.yml create mode 100644 queries/Computers with membership in Protected Users.yml create mode 100644 queries/Computers with non-default Primary Group membership.yml create mode 100644 queries/Computers with passwords older than the default maximum password age.yml create mode 100644 queries/Computers with the WebClient running.yml create mode 100644 queries/Computers with the outgoing NTLM setting set to Deny all.yml create mode 100644 queries/Computers with unsupported operating systems.yml create mode 100644 queries/Cross-forest trusts with abusable configuration.yml create mode 100644 queries/DCs vulnerable to NTLM relay to LDAP attacks.yml create mode 100644 queries/Dangerous privileges for Domain Users groups.yml create mode 100644 queries/Devices with unsupported operating systems.yml create mode 100644 queries/Disabled Tier Zero High Value principals - AD.yml create mode 100644 queries/Disabled Tier Zero High Value principals - AZ.yml create mode 100644 queries/Domain Admins logons to non-Domain Controllers.yml create mode 100644 queries/Domain Controllers allowing NTLMv1 or LM authentication.yml create mode 100644 queries/Domain controllers with UPN certificate mapping enabled.yml create mode 100644 queries/Domain controllers with weak certificate binding enabled.yml create mode 100644 queries/Domain migration groups.yml create mode 100644 queries/Domains affected by AdPrep privilege escalation risk.yml create mode 100644 queries/Domains affected by Exchange privilege escalation risk.yml create mode 100644 queries/Domains allowing authenticated domain enumeration.yml create mode 100644 queries/Domains allowing unauthenticated NSPI RPC binds.yml create mode 100644 queries/Domains allowing unauthenticated domain enumeration.yml create mode 100644 queries/Domains allowing unauthenticated rootDSE searches and binds.yml create mode 100644 queries/Domains exempting privileged groups from AdminSDHolder protections.yml create mode 100644 queries/Domains not mitigating CVE-2021-42291.yml create mode 100644 queries/Domains not verifying UPN and SPN uniqueness.yml create mode 100644 queries/Domains where any user can join a computer to the domain.yml create mode 100644 queries/Domains with List Object mode enabled.yml create mode 100644 queries/Domains with a minimum default password policy length less than 15 characters.yml create mode 100644 queries/Domains with a single-point-of-failure Domain Controller.yml create mode 100644 queries/Domains with functional level not the latest version.yml create mode 100644 queries/Domains with more than 50 Tier Zero accounts.yml create mode 100644 queries/Domains with smart card accounts where smart account passwords do not expire.yml create mode 100644 queries/Domains without Microsoft LAPS computers.yml create mode 100644 queries/Domains without Protected Users group.yml create mode 100644 queries/Domains without automatic password rotation on smart card accounts.yml create mode 100644 queries/ESC8-vulnerable Enterprise CAs.yml create mode 100644 queries/Enabled Tier Zero High Value principals inactive for 60 days.yml create mode 100644 queries/Enabled built-in guest user accounts.yml create mode 100644 queries/Enabled computers inactive for 180 days - MSSQL Failover Cluster.yml create mode 100644 queries/Enabled computers inactive for 180 days.yml create mode 100644 queries/Enabled users inactive for 180 days.yml create mode 100644 queries/Enrollment rights on CertTemplates with OIDGroupLink.yml create mode 100644 queries/Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled.yml create mode 100644 queries/Enrollment rights on published ESC1 certificate templates.yml create mode 100644 queries/Enrollment rights on published ESC2 certificate templates.yml create mode 100644 queries/Enrollment rights on published certificate templates with no security extension.yml create mode 100644 queries/Enrollment rights on published certificate templates.yml create mode 100644 queries/Enrollment rights on published enrollment agent certificate templates.yml create mode 100644 queries/Entra ID SSO accounts not rolling Kerberos decryption key.yml create mode 100644 queries/Entra Users synced from On-Prem Users added to Domain Admins group.yml create mode 100644 queries/Foreign principals in Tier Zero High Value targets.yml create mode 100644 queries/KRBTGT accounts with passwords not rotated in over 1 year.yml create mode 100644 queries/Kerberoastable members of Tier Zero High Value groups.yml create mode 100644 queries/Kerberoastable users with most admin privileges.yml create mode 100644 queries/Kerberos-enabled service account member of built-in Admins groups.yml create mode 100644 queries/Kerberos-enabled service accounts without AES encryption support.yml create mode 100644 queries/Large default group added to computer-local group.yml create mode 100644 queries/Large default groups with outbound control of OUs.yml create mode 100644 queries/Large default groups with outbound control.yml create mode 100644 queries/Locations of Tier Zero High Value objects.yml create mode 100644 queries/Map Azure Management structure.yml create mode 100644 queries/Map OU structure.yml create mode 100644 queries/Map domain trusts.yml create mode 100644 queries/Members of Allowed RODC Password Replication Group.yml create mode 100644 queries/Nested groups within Tier Zero High Value.yml create mode 100644 queries/Non-Tier Zero account with 'Admin Count' flag.yml create mode 100644 queries/Non-Tier Zero account with excessive control.yml create mode 100644 queries/Non-Tier Zero account with unconstrained delegation.yml create mode 100644 queries/Non-Tier Zero accounts with SID History of Tier Zero accounts.yml create mode 100644 queries/Non-Tier Zero principals with BadSuccessor rights (no prerequisites check).yml create mode 100644 queries/Non-Tier Zero principals with BadSuccessor rights (with prerequisites check).yml create mode 100644 queries/Non-Tier Zero principals with control of AdminSDHolder.yml create mode 100644 queries/Non-default delegation on MicrosoftDNS container.yml create mode 100644 queries/Non-default members in Pre-Windows 2000 Compatible Access.yml create mode 100644 queries/Non-default permissions on IssuancePolicy nodes.yml create mode 100644 queries/Object name conflict.yml create mode 100644 queries/On-Prem Users synced to Entra Users that Own Entra Objects.yml create mode 100644 queries/On-Prem Users synced to Entra Users with Azure RM Roles (direct).yml create mode 100644 queries/On-Prem Users synced to Entra Users with Azure RM Roles (group delegated).yml create mode 100644 queries/On-Prem Users synced to Entra Users with Entra Admin Roles (direct).yml create mode 100644 queries/On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated).yml create mode 100644 queries/On-Prem Users synced to Entra Users with Entra Group Membership.yml create mode 100644 queries/PKI hierarchy.yml create mode 100644 queries/Paths from Domain Users to Tier Zero High Value targets.yml create mode 100644 queries/Principal with SPN keyword.yml create mode 100644 queries/Principals with DCSync privileges.yml create mode 100644 queries/Principals with DES-only Kerberos authentication.yml create mode 100644 queries/Principals with foreign domain group membership.yml create mode 100644 queries/Principals with passwords stored using reversible encryption.yml create mode 100644 queries/Principals with weak supported Kerberos encryption types.yml create mode 100644 queries/Public Key Services container.yml create mode 100644 queries/Servers where Domain Users can RDP.yml create mode 100644 queries/Sessions across trusts.yml create mode 100644 queries/Shortest paths from Azure Applications to Tier Zero High Value targets.yml create mode 100644 queries/Shortest paths from Domain Users to Tier Zero High Value targets.yml create mode 100644 queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml create mode 100644 queries/Shortest paths from Owned objects to Tier Zero.yml create mode 100644 queries/Shortest paths from Owned objects.yml create mode 100644 queries/Shortest paths to Azure Subscriptions.yml create mode 100644 queries/Shortest paths to Domain Admins from Kerberoastable users.yml create mode 100644 queries/Shortest paths to Domain Admins.yml create mode 100644 queries/Shortest paths to Tier Zero High Value targets.yml create mode 100644 queries/Shortest paths to privileged roles.yml create mode 100644 queries/Shortest paths to systems trusted for unconstrained delegation.yml create mode 100644 queries/Smart card accounts with passwords not rotated in over 1 year.yml create mode 100644 queries/Tier Zero AD principals synchronized with Entra ID.yml create mode 100644 queries/Tier Zero High Value enabled users not requiring smart card authentication.yml create mode 100644 queries/Tier Zero High Value external Entra ID users.yml create mode 100644 queries/Tier Zero High Value users with non-expiring passwords.yml create mode 100644 queries/Tier Zero accounts not members of Denied RODC Password Replication Group.yml create mode 100644 queries/Tier Zero accounts that can be delegated.yml create mode 100644 queries/Tier Zero computers at risk of constrained delegation.yml create mode 100644 queries/Tier Zero computers at risk of resource-based constrained delegation.yml create mode 100644 queries/Tier Zero computers not owned by Tier Zero.yml create mode 100644 queries/Tier Zero computers not requiring inbound SMB signing.yml create mode 100644 queries/Tier Zero computers with passwords older than the default maximum password age.yml create mode 100644 queries/Tier Zero computers with the WebClient running.yml create mode 100644 queries/Tier Zero computers with unsupported operating systems.yml create mode 100644 queries/Tier Zero users not member of Protected Users.yml create mode 100644 queries/Tier Zero users with email.yml create mode 100644 queries/Tier Zero users with passwords not rotated in over 1 year.yml create mode 100644 queries/Trace ACE inheritance.yml create mode 100644 queries/Unresolved SID with outbound control.yml create mode 100644 queries/Usage of built-in domain Administrator account.yml create mode 100644 queries/Users which do not require password to authenticate.yml create mode 100644 queries/Users with logon scripts stored in a trusted domain.yml create mode 100644 queries/Users with non-default Primary Group membership.yml create mode 100644 queries/Users with non-expiring passwords.yml create mode 100644 queries/Users with passwords not rotated in over 1 year.yml create mode 100644 queries/Workstations where Domain Users can RDP.yml diff --git a/queries/ACEs across trusts.yml b/queries/ACEs across trusts.yml new file mode 100644 index 0000000..a170a8e --- /dev/null +++ b/queries/ACEs across trusts.yml @@ -0,0 +1,18 @@ +name: ACEs across trusts +guid: c902d3b4-1a75-4335-acd7-28246dab746d +prebuilt: false +platform: 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) + WHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid + AND r.isacl + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgement: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/AS-REP Roastable Tier Zero users (DontReqPreAuth).yml b/queries/AS-REP Roastable Tier Zero users (DontReqPreAuth).yml new file mode 100644 index 0000000..a363c4d --- /dev/null +++ b/queries/AS-REP Roastable Tier Zero users (DontReqPreAuth).yml @@ -0,0 +1,16 @@ +name: AS-REP Roastable Tier Zero users (DontReqPreAuth) +guid: 6d51e4dc-e1ad-477a-b6c6-324f18f03120 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.dontreqpreauth = true + RETURN n +note: +revision: 1 +resources: https://attack.mitre.org/techniques/T1558/004/ +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/AS-REP Roastable users (DontReqPreAuth).yml b/queries/AS-REP Roastable users (DontReqPreAuth).yml new file mode 100644 index 0000000..91285ec --- /dev/null +++ b/queries/AS-REP Roastable users (DontReqPreAuth).yml @@ -0,0 +1,17 @@ +name: AS-REP Roastable users (DontReqPreAuth) +guid: 2570e359-dec1-419d-b0dc-a204bd64ee42 +prebuilt: true +platform: Active Directory +category: Kerberos Interaction +description: +query: |- + MATCH (u:User) + WHERE u.dontreqpreauth = true + AND u.enabled = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: https://attack.mitre.org/techniques/T1558/004/ +acknowledgements: + diff --git a/queries/Accounts with SID History to a non-existent domain.yml b/queries/Accounts with SID History to a non-existent domain.yml new file mode 100644 index 0000000..c7e1a49 --- /dev/null +++ b/queries/Accounts with SID History to a non-existent domain.yml @@ -0,0 +1,17 @@ +name: Accounts with SID History to a non-existent domain +guid: 2710401a-c4c2-4d2c-9edb-d7625045f2e8 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (d:Domain) + WITH collect(d.objectid) AS domainSIDs + MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base) + WHERE NOT n.domainsid IN domainSIDs + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Accounts with SID History to a same-domain account.yml b/queries/Accounts with SID History to a same-domain account.yml new file mode 100644 index 0000000..7605550 --- /dev/null +++ b/queries/Accounts with SID History to a same-domain account.yml @@ -0,0 +1,15 @@ +name: Accounts with SID History to a same-domain account +guid: 275d2d58-0cad-4cad-8103-e0874cece666 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base) + WHERE n.domainsid = m.domainsid + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Accounts with SID History.yml b/queries/Accounts with SID History.yml new file mode 100644 index 0000000..a3cd2b8 --- /dev/null +++ b/queries/Accounts with SID History.yml @@ -0,0 +1,14 @@ +name: Accounts with SID History +guid: 8172d52c-a975-49bd-9180-5b6efc59c9ab +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(:Base)-[:HasSIDHistory]->(:Base) + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Accounts with clear-text password attributes.yml b/queries/Accounts with clear-text password attributes.yml new file mode 100644 index 0000000..b187bd8 --- /dev/null +++ b/queries/Accounts with clear-text password attributes.yml @@ -0,0 +1,18 @@ +name: Accounts with clear-text password attributes +guid: e303498f-e3d4-489d-8a34-b68e187bc4e7 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE n.userpassword IS NOT NULL + OR n.unixpassword IS NOT NULL + OR n.unicodepwd IS NOT NULL + OR n.msSFU30Password IS NOT NULL + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/AdminSDHolder protected Accounts and Groups.yml b/queries/AdminSDHolder protected Accounts and Groups.yml new file mode 100644 index 0000000..0c0e9b6 --- /dev/null +++ b/queries/AdminSDHolder protected Accounts and Groups.yml @@ -0,0 +1,22 @@ +name: AdminSDHolder protected Accounts and Groups +guid: 5ee2f40e-a55c-4140-ab8a-91746ba3752b +prebuilt: false +platform: 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) + WHERE ( + 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 + 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 + OR n.objectid =~ ".*-(500|502|516|521)$" // Direct objects + ) + RETURN n +note: +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 +acknowledgement: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All ADCS ESC privilege escalation edges.yml b/queries/All ADCS ESC privilege escalation edges.yml new file mode 100644 index 0000000..5ebf2cc --- /dev/null +++ b/queries/All ADCS ESC privilege escalation edges.yml @@ -0,0 +1,20 @@ +name: All ADCS ESC privilege escalation edges +guid: 49db8edc-8421-438f-b97b-23c042959bef +prebuilt: false +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p=(:Base)-[:ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|GoldenCert|CoerceAndRelayNTLMToADCS]->(:Base) + RETURN p +note: +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ülow Knudsen, @Jonas_B_K + diff --git a/queries/All DNSAdmins.yml b/queries/All DNSAdmins.yml new file mode 100644 index 0000000..016983c --- /dev/null +++ b/queries/All DNSAdmins.yml @@ -0,0 +1,15 @@ +name: All DNSAdmins +guid: 183fb320-f3ae-4ab3-a090-3f9a7db692e1 +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p=(n:Base)-[:MemberOf]->(g:Group) + WHERE n.name STARTS WITH "DNSADMINS@" + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All Domain Admins.yml b/queries/All Domain Admins.yml new file mode 100644 index 0000000..7aaa9c9 --- /dev/null +++ b/queries/All Domain Admins.yml @@ -0,0 +1,16 @@ +name: All Domain Admins +guid: 0596dba7-9180-49a0-aa54-00243240037c +prebuilt: true +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p = (t:Group)<-[:MemberOf*1..]-(a) + WHERE (a:User or a:Computer) and t.objectid ENDS WITH '-512' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/All Global Administrators.yml b/queries/All Global Administrators.yml new file mode 100644 index 0000000..b74e56e --- /dev/null +++ b/queries/All Global Administrators.yml @@ -0,0 +1,15 @@ +name: All Global Administrators +guid: 94d7d765-6837-4eb8-aa33-e1c9ef262cdc +prebuilt: true +platform: Azure +category: General +description: +query: |- + MATCH p = (:AZBase)-[:AZGlobalAdmin*1..]->(:AZTenant) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/All Kerberoastable users.yml b/queries/All Kerberoastable users.yml new file mode 100644 index 0000000..a5385bb --- /dev/null +++ b/queries/All Kerberoastable users.yml @@ -0,0 +1,20 @@ +name: All Kerberoastable users +guid: 14ab4eaa-b73b-49c4-b2d1-1e020757c995 +prebuilt: true +platform: Active Directory +category: Kerberos Interaction +description: +query: |- + MATCH (u:User) + WHERE u.hasspn=true + AND u.enabled = true + AND NOT u.objectid ENDS WITH '-502' + AND NOT COALESCE(u.gmsa, false) = true + AND NOT COALESCE(u.msa, false) = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: https://attack.mitre.org/techniques/T1558/003/ +acknowledgements: + diff --git a/queries/All Operator groups.yml b/queries/All Operator groups.yml new file mode 100644 index 0000000..3fac95d --- /dev/null +++ b/queries/All Operator groups.yml @@ -0,0 +1,23 @@ +name: All Operators +guid: 3dfd0843-1ff9-4c21-aa67-feae08d109de +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p=(:Base)-[:MemberOf]->(n:Group) + WHERE ( + n.objectid ENDS WITH 'S-1-5-32-551' OR // Backup Operators + n.objectid ENDS WITH 'S-1-5-32-556' OR // Network Configuration Operators + n.objectid ENDS WITH 'S-1-5-32-549' OR // Server Operators + n.objectid ENDS WITH 'S-1-5-32-579' OR // Access Control Assistance Operators + n.objectid ENDS WITH 'S-1-5-32-548' OR // Account Operators + n.objectid ENDS WITH 'S-1-5-32-569' OR // Cryptographic Operators + n.objectid ENDS WITH 'S-1-5-32-550' // Print Operators + ) + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All Schema Admins.yml b/queries/All Schema Admins.yml new file mode 100644 index 0000000..1887192 --- /dev/null +++ b/queries/All Schema Admins.yml @@ -0,0 +1,16 @@ +name: All Schema Admins +guid: 76d8e61d-7a86-40ff-8a85-fd37f1e2563f +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p=(n:Base)-[:MemberOf*1..]->(m:Group) + WHERE (n:User OR n:Computer) + AND m.objectid ENDS WITH "-518" // Schema Admins + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All coerce and NTLM relay edges.yml b/queries/All coerce and NTLM relay edges.yml new file mode 100644 index 0000000..51b91a0 --- /dev/null +++ b/queries/All coerce and NTLM relay edges.yml @@ -0,0 +1,14 @@ +name: All coerce and NTLM relay edges +guid: 15c5ff3b-856c-44d1-a731-a8cb72512dd1 +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH p = (n:Base)-[:CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|CoerceAndRelayNTLMToADCS|CoerceAndRelayNTLMToSMB]->(:Base) + RETURN p LIMIT 500 +note: +revision: 1 +resources: https://specterops.io/blog/2025/04/08/the-renaissance-of-ntlm-relay-attacks-everything-you-need-to-know/ +acknowledgements: + diff --git a/queries/All incoming and local paths for a specific computer.yml b/queries/All incoming and local paths for a specific computer.yml new file mode 100644 index 0000000..c6027a4 --- /dev/null +++ b/queries/All incoming and local paths for a specific computer.yml @@ -0,0 +1,18 @@ +name: All incoming and local paths for a specific computer +guid: 1f67e538-19d4-4020-89c8-5b39b31571bd +prebuilt: false +platform: 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 + MATCH p=(n:Base)-[:RemoteInteractiveLogonPrivilege|AdminTo|CanRDP|LocalToComputer|MemberOfLocalGroup]-(m:Base) + WHERE m.name CONTAINS 'HOSTNAME' + AND m.name CONTAINS '.' // Only see computer-related objects (eg. not AD Groups) + RETURN p +note: +revision: 1 +resources: +acknowledgement: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All members of high privileged roles.yml b/queries/All members of high privileged roles.yml new file mode 100644 index 0000000..96c312e --- /dev/null +++ b/queries/All members of high privileged roles.yml @@ -0,0 +1,16 @@ +name: All members of high privileged roles +guid: 3df24d92-dd12-4125-811b-e696b098f60e +prebuilt: true +platform: Azure +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' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/All paths crossing a specific trust.yml b/queries/All paths crossing a specific trust.yml new file mode 100644 index 0000000..f8fed6f --- /dev/null +++ b/queries/All paths crossing a specific trust.yml @@ -0,0 +1,20 @@ +name: All paths crossing a specific trust +guid: 251fc893-7a6b-4a0a-8650-9d5408d38c3c +prebuilt: false +platform: Active Directory +category: Domain Information +description: All paths crossing a specific trust from a trusted to a trusting domain. +query: |- + // Replace the TRUSTED domain SID + // Replace the TRUSTING domain SID + MATCH p=(Trusted:Base)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation]->(Trusting:Base) + WHERE Trusted.domainsid = 'S-1-5-21-1111111111-1111111111-1111111111' + AND Trusting.domainsid = 'S-1-5-21-2222222222-2222222222-2222222222' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgement: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/All service principals with Microsoft Graph App Role assignments.yml b/queries/All service principals with Microsoft Graph App Role assignments.yml new file mode 100644 index 0000000..59a4ad9 --- /dev/null +++ b/queries/All service principals with Microsoft Graph App Role assignments.yml @@ -0,0 +1,15 @@ +name: All service principals with Microsoft Graph App Role assignments +guid: 74440269-eb41-476b-8dec-b4095569b029 +prebuilt: true +platform: Azure +category: Microsoft Graph +description: +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) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/All service principals with Microsoft Graph privilege to grant arbitrary App Roles.yml b/queries/All service principals with Microsoft Graph privilege to grant arbitrary App Roles.yml new file mode 100644 index 0000000..a76a982 --- /dev/null +++ b/queries/All service principals with Microsoft Graph privilege to grant arbitrary App Roles.yml @@ -0,0 +1,15 @@ +name: All service principals with Microsoft Graph privilege to grant arbitrary App Roles +guid: e6d6b5da-89da-4514-a409-2d6e368397da +prebuilt: true +platform: Azure +category: Microsoft Graph +description: +query: |- + MATCH p=(:AZServicePrincipal)-[:AZMGGrantAppRoles]->(:AZTenant) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/CA administrators and CA managers.yml b/queries/CA administrators and CA managers.yml new file mode 100644 index 0000000..04cd20a --- /dev/null +++ b/queries/CA administrators and CA managers.yml @@ -0,0 +1,15 @@ +name: CA administrators and CA managers +guid: fd35e3d8-0c74-4b5a-a847-c0dd1f1c9f19 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:ManageCertificates|ManageCA]->(:EnterpriseCA) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computer owners who can obtain LAPS passwords.yml b/queries/Computer owners who can obtain LAPS passwords.yml new file mode 100644 index 0000000..b22bc4c --- /dev/null +++ b/queries/Computer owners who can obtain LAPS passwords.yml @@ -0,0 +1,15 @@ +name: Computer owners who can obtain LAPS passwords +guid: 92aa81d6-b08e-4abb-ae39-ecbe5735a74c +prebuilt: false +platform: 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) + WHERE c.haslaps = true AND c.ownersid = n.objectid + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Computers not requiring inbound SMB signing.yml b/queries/Computers not requiring inbound SMB signing.yml new file mode 100644 index 0000000..997b6fd --- /dev/null +++ b/queries/Computers not requiring inbound SMB signing.yml @@ -0,0 +1,15 @@ +name: Computers not requiring inbound SMB signing +guid: 6b1fcfb6-b010-41a2-9d31-f9872fe994ff +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (n:Computer) + WHERE n.smbsigning = False + RETURN n +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers where Domain Users are local administrators.yml b/queries/Computers where Domain Users are local administrators.yml new file mode 100644 index 0000000..5f6bb7a --- /dev/null +++ b/queries/Computers where Domain Users are local administrators.yml @@ -0,0 +1,16 @@ +name: Computers where Domain Users are local administrators +guid: d43a7bdc-33c6-4a39-a3bb-24115749e595 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Group)-[:AdminTo]->(:Computer) + WHERE s.objectid ENDS WITH '-513' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers where Domain Users can read LAPS passwords.yml b/queries/Computers where Domain Users can read LAPS passwords.yml new file mode 100644 index 0000000..187271e --- /dev/null +++ b/queries/Computers where Domain Users can read LAPS passwords.yml @@ -0,0 +1,16 @@ +name: Computers where Domain Users can read LAPS passwords +guid: aa4bfa95-e7b9-4d56-8f35-f34f04d7b6f4 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Group)-[:AllExtendedRights|ReadLAPSPassword]->(:Computer) + WHERE s.objectid ENDS WITH '-513' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers with membership in Protected Users.yml b/queries/Computers with membership in Protected Users.yml new file mode 100644 index 0000000..ff115f8 --- /dev/null +++ b/queries/Computers with membership in Protected Users.yml @@ -0,0 +1,15 @@ +name: Computers with membership in Protected Users +guid: a26372f4-2e92-49f6-8993-6657fbc1569a +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH p = (:Base)-[:MemberOf*1..]->(g:Group) + WHERE g.objectid ENDS WITH "-525" + RETURN p LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers with non-default Primary Group membership.yml b/queries/Computers with non-default Primary Group membership.yml new file mode 100644 index 0000000..922a645 --- /dev/null +++ b/queries/Computers with non-default Primary Group membership.yml @@ -0,0 +1,18 @@ +name: Computers with non-default Primary Group membership +guid: 5862dc4e-6f6f-4321-9474-d838968495ed +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Computer)-[r:MemberOf]->(g:Group) + WHERE NOT g.objectid ENDS WITH "-515" // Domain Computers + AND NOT g.objectid ENDS WITH "-516" // Domain Controllers + AND NOT g.objectid ENDS WITH "-521" // Read-Only Domain Controllers + AND r.isprimarygroup = true + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Computers with passwords older than the default maximum password age.yml b/queries/Computers with passwords older than the default maximum password age.yml new file mode 100644 index 0000000..e0b3f2a --- /dev/null +++ b/queries/Computers with passwords older than the default maximum password age.yml @@ -0,0 +1,20 @@ +name: Computers with passwords older than the default maximum password age +guid: 185c5010-8d4f-4f9b-b24e-831707dddfca +prebuilt: false +platform: 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 + MATCH (n:Computer) + WHERE n.pwdlastset < (datetime().epochseconds - (rotation_period * 86400)) // password not rotated + AND n.enabled = true // enabled computers + AND n.whencreated < (datetime().epochseconds - (rotation_period * 86400)) // exclude recently created computers + AND n.lastlogontimestamp > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Replicated value) + AND n.lastlogon > (datetime().epochseconds - (rotation_period * 86400)) // active computers (Non-replicated value) + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/disable-machine-account-password +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Computers with the WebClient running.yml b/queries/Computers with the WebClient running.yml new file mode 100644 index 0000000..df6327d --- /dev/null +++ b/queries/Computers with the WebClient running.yml @@ -0,0 +1,15 @@ +name: Computers with the WebClient running +guid: 51107ad1-f0bc-43d3-a561-5cee471ca196 +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (c:Computer) + WHERE c.webclientrunning = True + RETURN c LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers with the outgoing NTLM setting set to Deny all.yml b/queries/Computers with the outgoing NTLM setting set to Deny all.yml new file mode 100644 index 0000000..4d2ee63 --- /dev/null +++ b/queries/Computers with the outgoing NTLM setting set to Deny all.yml @@ -0,0 +1,15 @@ +name: Computers with the outgoing NTLM setting set to Deny all +guid: a9ddca74-feeb-4dbf-8b0f-de08b3cfa8a6 +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (c:Computer) + WHERE c.restrictoutboundntlm = True + RETURN c LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Computers with unsupported operating systems.yml b/queries/Computers with unsupported operating systems.yml new file mode 100644 index 0000000..5a7db47 --- /dev/null +++ b/queries/Computers with unsupported operating systems.yml @@ -0,0 +1,16 @@ +name: Computers with unsupported operating systems +guid: d06d3b14-0318-4fa9-9639-4b79ccaf3c2c +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (c:Computer) + WHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*' + RETURN c + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Cross-forest trusts with abusable configuration.yml b/queries/Cross-forest trusts with abusable configuration.yml new file mode 100644 index 0000000..e8c88fe --- /dev/null +++ b/queries/Cross-forest trusts with abusable configuration.yml @@ -0,0 +1,15 @@ +name: Cross-forest trusts with abusable configuration +guid: 5cf1f354-80d4-420e-bc4b-424fabc21a56 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Domain)-[:CrossForestTrust|SpoofSIDHistory|AbuseTGTDelegation]-(m:Domain) + WHERE (n)-[:SpoofSIDHistory|AbuseTGTDelegation]-(m) + RETURN p +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/DCs vulnerable to NTLM relay to LDAP attacks.yml b/queries/DCs vulnerable to NTLM relay to LDAP attacks.yml new file mode 100644 index 0000000..a07adb0 --- /dev/null +++ b/queries/DCs vulnerable to NTLM relay to LDAP attacks.yml @@ -0,0 +1,17 @@ +name: DCs vulnerable to NTLM relay to LDAP attacks +guid: 3f87e0b0-fc06-4986-a94c-e08781253dc8 +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH p = (dc:Computer)-[:DCFor]->(:Domain) + WHERE (dc.ldapavailable = True AND dc.ldapsigning = False) + OR (dc.ldapsavailable = True AND dc.ldapsepa = False) + OR (dc.ldapavailable = True AND dc.ldapsavailable = True AND dc.ldapsigning = False and dc.ldapsepa = True) + RETURN p +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Dangerous privileges for Domain Users groups.yml b/queries/Dangerous privileges for Domain Users groups.yml new file mode 100644 index 0000000..dd1fb93 --- /dev/null +++ b/queries/Dangerous privileges for Domain Users groups.yml @@ -0,0 +1,16 @@ +name: Dangerous privileges for Domain Users groups +guid: 9b8b9c18-f8c6-4c54-a20f-de0f7a7edbe0 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Group)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation]->(:Base) + WHERE s.objectid ENDS WITH '-513' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Devices with unsupported operating systems.yml b/queries/Devices with unsupported operating systems.yml new file mode 100644 index 0000000..42abc49 --- /dev/null +++ b/queries/Devices with unsupported operating systems.yml @@ -0,0 +1,17 @@ +name: Devices with unsupported operating systems +guid: e3f2b53a-7ce6-4e52-9c74-68b69338288b +prebuilt: true +platform: Azure +category: Azure Hygiene +description: +query: |- + MATCH (n:AZDevice) + WHERE n.operatingsystem CONTAINS 'WINDOWS' + AND 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).?.*' + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Disabled Tier Zero High Value principals - AD.yml b/queries/Disabled Tier Zero High Value principals - AD.yml new file mode 100644 index 0000000..693bc2b --- /dev/null +++ b/queries/Disabled Tier Zero High Value principals - AD.yml @@ -0,0 +1,19 @@ +name: Disabled Tier Zero / High Value principals +guid: d65a801f-d3ef-4b7e-8030-99ebfd6dad12 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.enabled = false + AND NOT n.objectid ENDS WITH '-502' // Removes false positive, KRBTGT + AND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Disabled Tier Zero High Value principals - AZ.yml b/queries/Disabled Tier Zero High Value principals - AZ.yml new file mode 100644 index 0000000..a0582ab --- /dev/null +++ b/queries/Disabled Tier Zero High Value principals - AZ.yml @@ -0,0 +1,17 @@ +name: Disabled Tier Zero / High Value principals +guid: 860d5c2d-84fe-4c85-80de-e0a9badbd0e7 +prebuilt: true +platform: Azure +category: Azure Hygiene +description: +query: |- + MATCH (n:AZBase) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.enabled = false + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Domain Admins logons to non-Domain Controllers.yml b/queries/Domain Admins logons to non-Domain Controllers.yml new file mode 100644 index 0000000..a590c9f --- /dev/null +++ b/queries/Domain Admins logons to non-Domain Controllers.yml @@ -0,0 +1,19 @@ +name: Domain Admins logons to non-Domain Controllers +guid: e2f3fd0a-1df2-4089-b0a4-272ad6e369a9 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH (s)-[:MemberOf*0..]->(g:Group) + WHERE g.objectid ENDS WITH '-516' + WITH COLLECT(s) AS exclude + MATCH p = (c:Computer)-[:HasSession]->(:User)-[:MemberOf*1..]->(g:Group) + WHERE g.objectid ENDS WITH '-512' AND NOT c IN exclude + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Domain Controllers allowing NTLMv1 or LM authentication.yml b/queries/Domain Controllers allowing NTLMv1 or LM authentication.yml new file mode 100644 index 0000000..b007ef2 --- /dev/null +++ b/queries/Domain Controllers allowing NTLMv1 or LM authentication.yml @@ -0,0 +1,16 @@ +name: Domain Controllers allowing NTLMv1 or LM authentication +guid: 4b42513c-f89d-47ff-8d98-908af49d2b48 +prebuilt: false +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (dc:Computer) + WHERE dc.isdc = true + AND (dc.lmcompatibilitylevel IS NOT NULL AND NOT dc.lmcompatibilitylevel = 5) + RETURN dc +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domain controllers with UPN certificate mapping enabled.yml b/queries/Domain controllers with UPN certificate mapping enabled.yml new file mode 100644 index 0000000..9afefc9 --- /dev/null +++ b/queries/Domain controllers with UPN certificate mapping enabled.yml @@ -0,0 +1,18 @@ +name: Domain controllers with UPN certificate mapping enabled +guid: 799ea3ce-572b-4594-98c4-041aa2ae6176 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (s:Computer)-[:DCFor]->(:Domain) + WHERE s.certificatemappingmethodsraw IN [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31] + RETURN p + LIMIT 1000 +note: +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ülow Knudsen, @Jonas_B_K + diff --git a/queries/Domain controllers with weak certificate binding enabled.yml b/queries/Domain controllers with weak certificate binding enabled.yml new file mode 100644 index 0000000..8991072 --- /dev/null +++ b/queries/Domain controllers with weak certificate binding enabled.yml @@ -0,0 +1,16 @@ +name: Domain controllers with weak certificate binding enabled +guid: a2444d99-10b5-412d-8fea-4b063cfddd2c +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (s:Computer)-[:DCFor]->(:Domain) + WHERE s.strongcertificatebindingenforcementraw = 0 OR s.strongcertificatebindingenforcementraw = 1 + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Domain migration groups.yml b/queries/Domain migration groups.yml new file mode 100644 index 0000000..16829ab --- /dev/null +++ b/queries/Domain migration groups.yml @@ -0,0 +1,15 @@ +name: Domain migration groups +guid: f39c4953-ae92-4d67-bb50-eb1a161d4d3f +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH (n:Group) + WHERE n.name CONTAINS "$$$@" + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains affected by AdPrep privilege escalation risk.yml b/queries/Domains affected by AdPrep privilege escalation risk.yml new file mode 100644 index 0000000..72d50b6 --- /dev/null +++ b/queries/Domains affected by AdPrep privilege escalation risk.yml @@ -0,0 +1,16 @@ +name: Domains affected by AdPrep privilege escalation risk +guid: 815ff190-f6f3-4757-a516-2f4bf589b705 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Group)-[r:GenericAll]->(m:Domain) + WHERE n.objectid ENDS WITH "-527" // Enterprise Key Admins + AND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains affected by Exchange privilege escalation risk.yml b/queries/Domains affected by Exchange privilege escalation risk.yml new file mode 100644 index 0000000..bc39172 --- /dev/null +++ b/queries/Domains affected by Exchange privilege escalation risk.yml @@ -0,0 +1,16 @@ +name: Domains affected by Exchange privilege escalation risk +guid: f2d09c94-b6f2-4901-9a2d-f8bacd61edc7 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Group)-[r:WriteDacl|ForceChangePassword|AddMember]->(m:Base) + WHERE n.name STARTS WITH "EXCHANGE " + AND ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains allowing authenticated domain enumeration.yml b/queries/Domains allowing authenticated domain enumeration.yml new file mode 100644 index 0000000..e3eda79 --- /dev/null +++ b/queries/Domains allowing authenticated domain enumeration.yml @@ -0,0 +1,16 @@ +name: Domains allowing authenticated domain enumeration +guid: 1e1e6fdd-6973-4547-906c-a494b5fbdcba +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Group)-[:MemberOf]->(m:Group) + WHERE n.objectid ENDS WITH "S-1-5-11" // Authenticated Users + AND m.objectid ENDS WITH "S-1-5-32-554" // Pre-Windows 2000 Compatible Access + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains allowing unauthenticated NSPI RPC binds.yml b/queries/Domains allowing unauthenticated NSPI RPC binds.yml new file mode 100644 index 0000000..a52da71 --- /dev/null +++ b/queries/Domains allowing unauthenticated NSPI RPC binds.yml @@ -0,0 +1,15 @@ +name: Domains allowing unauthenticated NSPI RPC binds +guid: a950fdab-5934-4c69-a88b-e2e0e3da9d52 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Checks the fAllowAnonNSPI flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{7}[^0].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains allowing unauthenticated domain enumeration.yml b/queries/Domains allowing unauthenticated domain enumeration.yml new file mode 100644 index 0000000..7c971e7 --- /dev/null +++ b/queries/Domains allowing unauthenticated domain enumeration.yml @@ -0,0 +1,17 @@ +name: Domains allowing unauthenticated domain enumeration +guid: 41a08d76-f8a5-4296-ad19-464c4c5c69fe +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Group)-[:MemberOf]->(m:Group) + WHERE (n.objectid ENDS WITH "S-1-5-7" // Anonymous + OR n.objectid ENDS WITH "S-1-1-0") // Everyone + AND m.objectid ENDS WITH "S-1-5-32-554" // Pre-Windows 2000 Compatible Access + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains allowing unauthenticated rootDSE searches and binds.yml b/queries/Domains allowing unauthenticated rootDSE searches and binds.yml new file mode 100644 index 0000000..97210c0 --- /dev/null +++ b/queries/Domains allowing unauthenticated rootDSE searches and binds.yml @@ -0,0 +1,15 @@ +name: Domains allowing unauthenticated rootDSE searches and binds +guid: ebc79aa4-e816-4be8-93fe-a0b30dbc771d +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Checks the fLDAPBlockAnonOps flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{6}[^2].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains exempting privileged groups from AdminSDHolder protections.yml b/queries/Domains exempting privileged groups from AdminSDHolder protections.yml new file mode 100644 index 0000000..a99ef25 --- /dev/null +++ b/queries/Domains exempting privileged groups from AdminSDHolder protections.yml @@ -0,0 +1,15 @@ +name: Domains exempting privileged groups from AdminSDHolder protections +guid: 79f8d8f9-8291-4bf7-a13a-15989018075f +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Checks the dwAdminSDExMask flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{15}[^0].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains not mitigating CVE-2021-42291.yml b/queries/Domains not mitigating CVE-2021-42291.yml new file mode 100644 index 0000000..bfab6c3 --- /dev/null +++ b/queries/Domains not mitigating CVE-2021-42291.yml @@ -0,0 +1,15 @@ +name: Domains not mitigating CVE-2021-42291 +guid: 02202726-d86d-46c2-891c-9770c635f76f +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Checks the AttributeAuthorizationOnLDAPAdd flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{27}[^1].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains not verifying UPN and SPN uniqueness.yml b/queries/Domains not verifying UPN and SPN uniqueness.yml new file mode 100644 index 0000000..bd76063 --- /dev/null +++ b/queries/Domains not verifying UPN and SPN uniqueness.yml @@ -0,0 +1,15 @@ +name: Domains not verifying UPN and SPN uniqueness +guid: cb0b1591-5c3e-45f1-afb7-984e5ad865d0 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Checks the DoNotVerifyUPNAndOrSPNUniqueness flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{20}[^0].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains where any user can join a computer to the domain.yml b/queries/Domains where any user can join a computer to the domain.yml new file mode 100644 index 0000000..5b5feec --- /dev/null +++ b/queries/Domains where any user can join a computer to the domain.yml @@ -0,0 +1,17 @@ +name: Domains where any user can join a computer to the domain +guid: 421921fa-bc0f-4659-9680-b7481adcb132 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Domain) + WHERE n.machineaccountquota > 0 + RETURN n +note: Does not check the 'Add workstations to domain' URA Security Policy on DCs. +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: + diff --git a/queries/Domains with List Object mode enabled.yml b/queries/Domains with List Object mode enabled.yml new file mode 100644 index 0000000..f1435a2 --- /dev/null +++ b/queries/Domains with List Object mode enabled.yml @@ -0,0 +1,15 @@ +name: Domains with List Object mode enabled +guid: 05e2a94b-5ee6-47ec-b715-3982f30af01b +prebuilt: false +platform: Active Directory +category: Domain Information +description: Checks the fDoListObject flag of dSHeuristics. +query: |- + MATCH (n:Domain) + WHERE n.dsheuristics =~ ".{2}[^0].*" + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/e5899be4-862e-496f-9a38-33950617d2c5 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains with a minimum default password policy length less than 15 characters.yml b/queries/Domains with a minimum default password policy length less than 15 characters.yml new file mode 100644 index 0000000..3256332 --- /dev/null +++ b/queries/Domains with a minimum default password policy length less than 15 characters.yml @@ -0,0 +1,15 @@ +name: Domains with a minimum default password policy length less than 15 characters +guid: 7d258d2d-a43d-4a90-85d7-71c946ae5fd7 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Domain) + WHERE n.minpwdlength < 15 + RETURN n +note: NIST recommends 15 characters. +revision: 1 +resources: https://pages.nist.gov/800-63-3/sp800-63b.html +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains with a single-point-of-failure Domain Controller.yml b/queries/Domains with a single-point-of-failure Domain Controller.yml new file mode 100644 index 0000000..e40697e --- /dev/null +++ b/queries/Domains with a single-point-of-failure Domain Controller.yml @@ -0,0 +1,17 @@ +name: Domains with a single-point-of-failure Domain Controller +guid: 3359a295-7cfd-491f-976b-c5a68647431c +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Group)<-[:MemberOf]-(:Computer) + WHERE n.objectid ENDS WITH '-516' + WITH n, COUNT(n) AS dcCount + WHERE dcCount = 1 + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains with functional level not the latest version.yml b/queries/Domains with functional level not the latest version.yml new file mode 100644 index 0000000..0829167 --- /dev/null +++ b/queries/Domains with functional level not the latest version.yml @@ -0,0 +1,15 @@ +name: Domains with functional level not the latest version +guid: 3da9d14a-f1cb-4df7-b3da-8d73ff5c401b +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Domain) + WHERE toString(n.functionallevel) IN ['2008','2003','2003 Interim','2000 Mixed/Native'] + RETURN n +note: Functional level <4 +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains with more than 50 Tier Zero accounts.yml b/queries/Domains with more than 50 Tier Zero accounts.yml new file mode 100644 index 0000000..47caf20 --- /dev/null +++ b/queries/Domains with more than 50 Tier Zero accounts.yml @@ -0,0 +1,17 @@ +name: Domains with more than 50 Tier Zero accounts +guid: f046e95a-5f84-4e83-bcda-6e83f3d8e21a +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (d:Domain)-[:Contains*1..]->(n:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + WITH d, COUNT(n) AS adminCount + WHERE adminCount > 50 + RETURN d +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains with smart card accounts where smart account passwords do not expire.yml b/queries/Domains with smart card accounts where smart account passwords do not expire.yml new file mode 100644 index 0000000..26fe8fc --- /dev/null +++ b/queries/Domains with smart card accounts where smart account passwords do not expire.yml @@ -0,0 +1,17 @@ +name: Domains with smart card accounts where smart account passwords do not expire +guid: 97e05e67-5961-4aba-a8e7-fe5f92334035 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (s:Domain)-[:Contains*1..]->(t:Base) + WHERE s.expirepasswordsonsmartcardonlyaccounts = false + AND t.enabled = true + AND t.smartcardrequired = true + RETURN s +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Domains without Microsoft LAPS computers.yml b/queries/Domains without Microsoft LAPS computers.yml new file mode 100644 index 0000000..2f15ddb --- /dev/null +++ b/queries/Domains without Microsoft LAPS computers.yml @@ -0,0 +1,18 @@ +name: Domains without Microsoft LAPS computers +guid: f9b440b5-732c-4ed3-b6d2-83857db17e1a +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH (d:Domain) + OPTIONAL MATCH (c:Computer) + WHERE c.domainsid = d.objectid AND c.haslaps = true + WITH d, COLLECT(c) AS computers + WHERE SIZE(computers) = 0 + RETURN d +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains without Protected Users group.yml b/queries/Domains without Protected Users group.yml new file mode 100644 index 0000000..0d3ba54 --- /dev/null +++ b/queries/Domains without Protected Users group.yml @@ -0,0 +1,20 @@ +name: Domains without Protected Users group +guid: 8c3e0811-a31b-45b4-a29d-1dce80fa2c5f +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH (n:Domain) + WHERE n.collected = true + OPTIONAL MATCH (m:Group) + WHERE m.name ENDS WITH n.name + AND m.objectid ENDS WITH '-525' + WITH n, m + WHERE m IS NULL + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Domains without automatic password rotation on smart card accounts.yml b/queries/Domains without automatic password rotation on smart card accounts.yml new file mode 100644 index 0000000..e8f6863 --- /dev/null +++ b/queries/Domains without automatic password rotation on smart card accounts.yml @@ -0,0 +1,17 @@ +name: Domains with smart card accounts where smart account passwords do not expire +guid: 97e05e67-5961-4aba-a8e7-fe5f92334035 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (s:Domain)-[:Contains*1..]->(t:Base) + WHERE s.expirepasswordsonsmartcardonlyaccounts = false + AND t.enabled = true + AND t.smartcardrequired = true + RETURN s +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/ESC8-vulnerable Enterprise CAs.yml b/queries/ESC8-vulnerable Enterprise CAs.yml new file mode 100644 index 0000000..6f28d01 --- /dev/null +++ b/queries/ESC8-vulnerable Enterprise CAs.yml @@ -0,0 +1,15 @@ +name: ESC8-vulnerable Enterprise CAs +guid: 60881923-296c-4702-adf7-a4f059dc9bb8 +prebuilt: true +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (n:EnterpriseCA) + WHERE n.hasvulnerableendpoint=true + RETURN n +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enabled Tier Zero High Value principals inactive for 60 days.yml b/queries/Enabled Tier Zero High Value principals inactive for 60 days.yml new file mode 100644 index 0000000..6cc410d --- /dev/null +++ b/queries/Enabled Tier Zero High Value principals inactive for 60 days.yml @@ -0,0 +1,23 @@ +name: Enabled Tier Zero / High Value principals inactive for 60 days +guid: 72550bcb-3c4f-463d-8973-91a49163dc5a +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 60 as inactive_days + MATCH (n:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.enabled = true + AND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value + AND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value + AND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals + AND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT + AND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator + AND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO + RETURN n +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enabled built-in guest user accounts.yml b/queries/Enabled built-in guest user accounts.yml new file mode 100644 index 0000000..795a0ed --- /dev/null +++ b/queries/Enabled built-in guest user accounts.yml @@ -0,0 +1,16 @@ +name: Enabled built-in guest user accounts +guid: bb0f620d-6a55-4413-ac74-4c82905e8598 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:User) + WHERE n.objectid ENDS WITH "-501" + AND n.enabled = true + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Enabled computers inactive for 180 days - MSSQL Failover Cluster.yml b/queries/Enabled computers inactive for 180 days - MSSQL Failover Cluster.yml new file mode 100644 index 0000000..1001a07 --- /dev/null +++ b/queries/Enabled computers inactive for 180 days - MSSQL Failover Cluster.yml @@ -0,0 +1,24 @@ +name: Enabled computers inactive for 180 days - MSSQL Failover Cluster +guid: d263e621-7f1b-4efb-ad25-098fc7d4fb72 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 180 as inactive_days + MATCH (n:Computer) + WHERE n.enabled = true + AND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value + AND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value + AND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals + AND ANY(type IN n.serviceprincipalnames WHERE + toLower(type) CONTAINS 'mssqlservercluster' OR + toLower(type) CONTAINS 'mssqlserverclustermgmtapi' OR + toLower(type) CONTAINS 'msclustervirtualserver') + RETURN n + LIMIT 1000 +note: +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 + diff --git a/queries/Enabled computers inactive for 180 days.yml b/queries/Enabled computers inactive for 180 days.yml new file mode 100644 index 0000000..fd6bc42 --- /dev/null +++ b/queries/Enabled computers inactive for 180 days.yml @@ -0,0 +1,22 @@ +name: Enabled computers inactive for 180 days +guid: 0768e810-1e1e-4319-a216-76d9c2058644 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 180 as inactive_days + MATCH (n:Computer) + WHERE n.enabled = true + AND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value + AND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value + AND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals + AND NOT n.name STARTS WITH 'AZUREADKERBEROS.' // Removes false positive, Azure KRBTGT + AND NOT n.name STARTS WITH 'AZUREADSSOACC.' // Removes false positive, Entra Seamless SSO + RETURN n + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Enabled users inactive for 180 days.yml b/queries/Enabled users inactive for 180 days.yml new file mode 100644 index 0000000..dca249d --- /dev/null +++ b/queries/Enabled users inactive for 180 days.yml @@ -0,0 +1,21 @@ +name: Enabled users inactive for 180 days +guid: 71972f3c-b32d-4023-a841-5cc8cc1c1867 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 180 as inactive_days + MATCH (n:User) + WHERE n.enabled = true + AND n.lastlogontimestamp < (datetime().epochseconds - (inactive_days * 86400)) // Replicated value + AND n.lastlogon < (datetime().epochseconds - (inactive_days * 86400)) // Non-replicated value + AND n.whencreated < (datetime().epochseconds - (inactive_days * 86400)) // Exclude recently created principals + AND NOT n.objectid ENDS WITH '-500' // Removes false positive, built-in Administrator + RETURN n + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Enrollment rights on CertTemplates with OIDGroupLink.yml b/queries/Enrollment rights on CertTemplates with OIDGroupLink.yml new file mode 100644 index 0000000..408e774 --- /dev/null +++ b/queries/Enrollment rights on CertTemplates with OIDGroupLink.yml @@ -0,0 +1,15 @@ +name: Enrollment rights on CertTemplates with OIDGroupLink +guid: 140a68eb-d21c-4b75-971f-309225fb2d75 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:ExtendedByPolicy]->(:IssuancePolicy)-[:OIDGroupLink]->(:Group) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled.yml b/queries/Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled.yml new file mode 100644 index 0000000..c214ae8 --- /dev/null +++ b/queries/Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled.yml @@ -0,0 +1,16 @@ +name: Enrollment rights on certificate templates published to Enterprise CA with User Specified SAN enabled +guid: 96e70597-2d74-4503-a624-f1e30b642894 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(eca:EnterpriseCA) + WHERE eca.isuserspecifiessanenabled = True + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on published ESC1 certificate templates.yml b/queries/Enrollment rights on published ESC1 certificate templates.yml new file mode 100644 index 0000000..62839fe --- /dev/null +++ b/queries/Enrollment rights on published ESC1 certificate templates.yml @@ -0,0 +1,19 @@ +name: Enrollment rights on published ESC1 certificate templates +guid: 2af855bc-f48f-4b22-9839-627d8231e425 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA) + WHERE ct.enrolleesuppliessubject = True + AND ct.authenticationenabled = True + AND ct.requiresmanagerapproval = False + AND (ct.authorizedsignatures = 0 OR ct.schemaversion = 1) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on published ESC2 certificate templates.yml b/queries/Enrollment rights on published ESC2 certificate templates.yml new file mode 100644 index 0000000..a6ea12b --- /dev/null +++ b/queries/Enrollment rights on published ESC2 certificate templates.yml @@ -0,0 +1,18 @@ +name: Enrollment rights on published ESC2 certificate templates +guid: ebc77984-1ceb-4ed2-a395-ce1067847941 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(c:CertTemplate)-[:PublishedTo]->(:EnterpriseCA) + WHERE c.requiresmanagerapproval = false + AND (c.effectiveekus = [''] OR '2.5.29.37.0' IN c.effectiveekus) + AND (c.authorizedsignatures = 0 OR c.schemaversion = 1) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on published certificate templates with no security extension.yml b/queries/Enrollment rights on published certificate templates with no security extension.yml new file mode 100644 index 0000000..f781a6c --- /dev/null +++ b/queries/Enrollment rights on published certificate templates with no security extension.yml @@ -0,0 +1,16 @@ +name: Enrollment rights on published certificate templates with no security extension +guid: 0677b70c-4e04-4e89-a6a2-f5764604a6a7 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA) + WHERE ct.nosecurityextension = true + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on published certificate templates.yml b/queries/Enrollment rights on published certificate templates.yml new file mode 100644 index 0000000..e95e17c --- /dev/null +++ b/queries/Enrollment rights on published certificate templates.yml @@ -0,0 +1,15 @@ +name: Enrollment rights on published certificate templates +guid: a4ae2e54-aad3-4bfd-a12d-90cb8a9cbc86 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(:CertTemplate)-[:PublishedTo]->(:EnterpriseCA) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Enrollment rights on published enrollment agent certificate templates.yml b/queries/Enrollment rights on published enrollment agent certificate templates.yml new file mode 100644 index 0000000..e872839 --- /dev/null +++ b/queries/Enrollment rights on published enrollment agent certificate templates.yml @@ -0,0 +1,18 @@ +name: Enrollment rights on published enrollment agent certificate templates +guid: 8483bf5b-89f1-4723-abb2-c48295f6393e +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (:Base)-[:Enroll|GenericAll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA) + WHERE '1.3.6.1.4.1.311.20.2.1' IN ct.effectiveekus + OR '2.5.29.37.0' IN ct.effectiveekus + OR SIZE(ct.effectiveekus) = 0 + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Entra ID SSO accounts not rolling Kerberos decryption key.yml b/queries/Entra ID SSO accounts not rolling Kerberos decryption key.yml new file mode 100644 index 0000000..dfd6158 --- /dev/null +++ b/queries/Entra ID SSO accounts not rolling Kerberos decryption key.yml @@ -0,0 +1,18 @@ +name: Entra ID SSO accounts not rolling Kerberos decryption key +guid: 1867abf8-08e3-4ea8-8f65-8366079d35c4 +prebuilt: false +platform: +- 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) + WHERE n.name STARTS WITH "AZUREADSSOACC." + AND n.pwdlastset < (datetime().epochseconds - (30 * 86400)) + RETURN n +note: +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 + diff --git a/queries/Entra Users synced from On-Prem Users added to Domain Admins group.yml b/queries/Entra Users synced from On-Prem Users added to Domain Admins group.yml new file mode 100644 index 0000000..0257d15 --- /dev/null +++ b/queries/Entra Users synced from On-Prem Users added to Domain Admins group.yml @@ -0,0 +1,18 @@ +name: Entra Users synced from On-Prem Users added to Domain Admins group +guid: 62722d5f-bd93-4d11-beeb-9be261827e4e +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:AZUser)-[:SyncedToADUser]->(:User)-[:MemberOf]->(t:Group) + WHERE t.objectid ENDS WITH '-512' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Foreign principals in Tier Zero High Value targets.yml b/queries/Foreign principals in Tier Zero High Value targets.yml new file mode 100644 index 0000000..8bddf70 --- /dev/null +++ b/queries/Foreign principals in Tier Zero High Value targets.yml @@ -0,0 +1,18 @@ +name: Foreign principals in Tier Zero / High Value targets +guid: 95bec736-86ef-4017-8465-9b9b66548b17 +prebuilt: true +platform: Azure +category: Azure Hygiene +description: +query: |- + MATCH (n:AZServicePrincipal) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND NOT toUpper(n.appownerorganizationid) = toUpper(n.tenantid) + AND n.appownerorganizationid CONTAINS '-' + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/KRBTGT accounts with passwords not rotated in over 1 year.yml b/queries/KRBTGT accounts with passwords not rotated in over 1 year.yml new file mode 100644 index 0000000..3e1b19e --- /dev/null +++ b/queries/KRBTGT accounts with passwords not rotated in over 1 year.yml @@ -0,0 +1,18 @@ +name: KRBTGT accounts with passwords not rotated in over 1 year +guid: 1b3ae310-ffa7-4ce5-a37f-6111aef600c8 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:User) + WHERE (n.objectid ENDS WITH '-502' + OR n.name STARTS WITH 'AZUREADKERBEROS.' + OR n.name STARTS WITH 'KRBTGT_AZUREAD@') + AND n.pwdlastset < (datetime().epochseconds - (365 * 86400)) + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Kerberoastable members of Tier Zero High Value groups.yml b/queries/Kerberoastable members of Tier Zero High Value groups.yml new file mode 100644 index 0000000..cee48d6 --- /dev/null +++ b/queries/Kerberoastable members of Tier Zero High Value groups.yml @@ -0,0 +1,20 @@ +name: Kerberoastable members of Tier Zero / High Value groups +guid: e6da7800-ae06-41cb-80a6-d5421ab2143a +prebuilt: true +platform: Active Directory +category: Kerberos Interaction +description: +query: |- + MATCH (u:User) + WHERE (u:Tag_Tier_Zero) AND u.hasspn=true + AND u.enabled = true + AND NOT u.objectid ENDS WITH '-502' + AND NOT COALESCE(u.gmsa, false) = true + AND NOT COALESCE(u.msa, false) = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: https://attack.mitre.org/techniques/T1558/003/ +acknowledgements: + diff --git a/queries/Kerberoastable users with most admin privileges.yml b/queries/Kerberoastable users with most admin privileges.yml new file mode 100644 index 0000000..a9bc680 --- /dev/null +++ b/queries/Kerberoastable users with most admin privileges.yml @@ -0,0 +1,23 @@ +name: Kerberoastable users with most admin privileges +guid: 9907b208-494c-4ba6-846d-485e6de14e17 +prebuilt: true +platform: Active Directory +category: Kerberos Interaction +description: +query: |- + MATCH (u:User) + WHERE u.hasspn = true + AND u.enabled = true + AND NOT u.objectid ENDS WITH '-502' + AND NOT COALESCE(u.gmsa, false) = true + AND NOT COALESCE(u.msa, false) = true + MATCH (u)-[:MemberOf|AdminTo*1..]->(c:Computer) + WITH DISTINCT u, COUNT(c) AS adminCount + RETURN u + ORDER BY adminCount DESC + LIMIT 100 +note: +revision: 1 +resources: https://attack.mitre.org/techniques/T1558/003/ +acknowledgements: + diff --git a/queries/Kerberos-enabled service account member of built-in Admins groups.yml b/queries/Kerberos-enabled service account member of built-in Admins groups.yml new file mode 100644 index 0000000..35f2e6d --- /dev/null +++ b/queries/Kerberos-enabled service account member of built-in Admins groups.yml @@ -0,0 +1,20 @@ +name: Kerberos-enabled service account member of built-in Admins groups +guid: 42a856fc-257a-4142-9592-ca95fd49e579 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Base)-[:MemberOf*1..]->(g:Group) + WHERE ( + g.objectid ENDS WITH '-512' // Domain Admins + OR g.objectid ENDS WITH '-519' // Enterprise Admins + OR g.objectid ENDS WITH '-518' // Schema Admins + ) + AND n.hasspn = true + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Kerberos-enabled service accounts without AES encryption support.yml b/queries/Kerberos-enabled service accounts without AES encryption support.yml new file mode 100644 index 0000000..fdbbe2d --- /dev/null +++ b/queries/Kerberos-enabled service accounts without AES encryption support.yml @@ -0,0 +1,24 @@ +name: Kerberos-enabled service accounts without AES encryption support +guid: cb8cf96e-21c9-422b-9439-390a13446ca6 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE n.hasspn = true + AND (( + n.supportedencryptiontypes <> ['Not defined'] + AND n.supportedencryptiontypes <> [] + AND NONE(type IN n.supportedencryptiontypes WHERE type CONTAINS 'AES128' OR type CONTAINS 'AES256') + ) + OR (n.pwdlastset < datetime('2008-02-27T00:00:00').epochseconds // Password Last Set before Windows Server 2008 + AND NOT n.pwdlastset IN [-1.0, 0.0] + )) + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Large default group added to computer-local group.yml b/queries/Large default group added to computer-local group.yml new file mode 100644 index 0000000..ad8efec --- /dev/null +++ b/queries/Large default group added to computer-local group.yml @@ -0,0 +1,16 @@ +name: Large default group added to computer-local group +guid: dde133d2-b4d2-4de9-a656-905f3bf066f3 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Group)-[:MemberOfLocalGroup]->(m:ADLocalGroup)-[:LocalToComputer]->(:Computer) + WHERE 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 + AND NOT m.objectid =~ ".*-(545|574|554)$" // Users, Certificate Service DCOM Access, Pre-Windows 2000 Compatible Access + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Large default groups with outbound control of OUs.yml b/queries/Large default groups with outbound control of OUs.yml new file mode 100644 index 0000000..4dfe3f1 --- /dev/null +++ b/queries/Large default groups with outbound control of OUs.yml @@ -0,0 +1,21 @@ +name: Large default groups with outbound control of OUs +guid: 310b3626-f8e6-4ab0-832c-72df6048597f +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Group)-[]->(:OU) + WHERE n.objectid ENDS WITH "-513" // DOMAIN USERS + OR n.objectid ENDS WITH "-515" // DOMAIN COMPUTERS + OR n.objectid ENDS WITH "-S-1-5-11" // AUTHENTICATED USERS + OR n.objectid ENDS WITH "-S-1-1-0" // EVERYONE + OR n.objectid ENDS WITH "S-1-5-32-545" // USERS + OR n.objectid ENDS WITH "S-1-5-32-546" // GUESTS + OR n.objectid ENDS WITH "S-1-5-7" // ANONYMOUS + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Large default groups with outbound control.yml b/queries/Large default groups with outbound control.yml new file mode 100644 index 0000000..93812ed --- /dev/null +++ b/queries/Large default groups with outbound control.yml @@ -0,0 +1,21 @@ +name: Large default groups with outbound control +guid: a334f21a-3d7f-448e-b7ea-1465a3127bce +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +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) + WHERE n.objectid ENDS WITH "-513" // DOMAIN USERS + OR n.objectid ENDS WITH "-515" // DOMAIN COMPUTERS + OR n.objectid ENDS WITH "-S-1-5-11" // AUTHENTICATED USERS + OR n.objectid ENDS WITH "-S-1-1-0" // EVERYONE + OR n.objectid ENDS WITH "S-1-5-32-545" // USERS + OR n.objectid ENDS WITH "S-1-5-32-546" // GUESTS + OR n.objectid ENDS WITH "S-1-5-7" // ANONYMOUS + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Locations of Tier Zero High Value objects.yml b/queries/Locations of Tier Zero High Value objects.yml new file mode 100644 index 0000000..81bf199 --- /dev/null +++ b/queries/Locations of Tier Zero High Value objects.yml @@ -0,0 +1,16 @@ +name: Locations of Tier Zero / High Value objects +guid: 18a83a17-b451-4343-acfe-7620516e2968 +prebuilt: true +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p = (t:Base)<-[:Contains*1..]-(:Domain) + WHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Map Azure Management structure.yml b/queries/Map Azure Management structure.yml new file mode 100644 index 0000000..818ac0d --- /dev/null +++ b/queries/Map Azure Management structure.yml @@ -0,0 +1,16 @@ +name: Map Azure Management structure +guid: c1bb109e-e6a4-4c91-864f-f78e1e42615e +prebuilt: false +platform: Azure +category: Kerberos Interaction +description: Maps the structure of Azure Management +query: |- + MATCH p = (:AZTenant)-[:AZContains*1..]->(:AZResourceGroup) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/azure/governance/management-groups/overview +acknowledgement: Martin Sohn Christensen, @martinsohndk +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Map OU structure.yml b/queries/Map OU structure.yml new file mode 100644 index 0000000..2b1b5ea --- /dev/null +++ b/queries/Map OU structure.yml @@ -0,0 +1,15 @@ +name: Map OU structure +guid: 8f14084b-5065-43d8-865a-a6ac52da25d1 +prebuilt: true +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p = (:Domain)-[:Contains*1..]->(:OU) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Map domain trusts.yml b/queries/Map domain trusts.yml new file mode 100644 index 0000000..2046ed0 --- /dev/null +++ b/queries/Map domain trusts.yml @@ -0,0 +1,15 @@ +name: Map domain trusts +guid: 268d3d26-5bc2-4820-a6ed-09d20f3d5413 +prebuilt: true +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p = (:Domain)-[:SameForestTrust|CrossForestTrust]->(:Domain) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Members of Allowed RODC Password Replication Group.yml b/queries/Members of Allowed RODC Password Replication Group.yml new file mode 100644 index 0000000..71e7aad --- /dev/null +++ b/queries/Members of Allowed RODC Password Replication Group.yml @@ -0,0 +1,16 @@ +name: Members of Allowed RODC Password Replication Group +guid: 19fc5acd-e30a-4038-a5b5-2e0494f93373 +prebuilt: false +platform: Active Directory +category: Domain Information +description: +query: |- + MATCH p=(n:Base)-[r:MemberOf]->(m:Group) + WHERE m.objectid ENDS WITH "-571" + AND (n:User or n:Computer) + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Nested groups within Tier Zero High Value.yml b/queries/Nested groups within Tier Zero High Value.yml new file mode 100644 index 0000000..155baa4 --- /dev/null +++ b/queries/Nested groups within Tier Zero High Value.yml @@ -0,0 +1,18 @@ +name: Nested groups within Tier Zero / High Value +guid: 8e541e75-df1d-423f-b429-4bbf0403a338 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(t:Group)<-[:MemberOf*..]-(s:Group) + WHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + AND NOT s.objectid ENDS WITH '-512' // Domain Admins + AND NOT s.objectid ENDS WITH '-519' // Enterprise Admins + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Non-Tier Zero account with 'Admin Count' flag.yml b/queries/Non-Tier Zero account with 'Admin Count' flag.yml new file mode 100644 index 0000000..b7fcdf4 --- /dev/null +++ b/queries/Non-Tier Zero account with 'Admin Count' flag.yml @@ -0,0 +1,16 @@ +name: Non-Tier Zero account with 'Admin Count' flag +guid: e7f703b3-5dba-4aef-8346-4d589be2c828 +prebuilt: false +platform: 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) + WHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.admincount = true + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/windows/win32/adschema/a-admincount +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero account with excessive control.yml b/queries/Non-Tier Zero account with excessive control.yml new file mode 100644 index 0000000..fcc2725 --- /dev/null +++ b/queries/Non-Tier Zero account with excessive control.yml @@ -0,0 +1,20 @@ +name: Non-Tier Zero account with excessive control +guid: 944cecfe-519b-4318-b226-e8520161b454 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH (d:Domain)-[:Contains*1..]->(u:User) + WHERE u.enabled = true + WITH d, COUNT(u) AS enabledUserCount + MATCH (d)-[:Contains*1..]->(n:Base)-[r:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|ForceChangePassword|AllExtendedRights|AddMember|AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions]->(m:Base) + WHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + WITH n, enabledUserCount, COLLECT(DISTINCT(m)) AS endNodes + WHERE SIZE(endNodes) >= 1000 + RETURN n +note: Finds Non-Tier Zero principals with control of >1000 Non-Tier Zero principals +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero account with unconstrained delegation.yml b/queries/Non-Tier Zero account with unconstrained delegation.yml new file mode 100644 index 0000000..b543012 --- /dev/null +++ b/queries/Non-Tier Zero account with unconstrained delegation.yml @@ -0,0 +1,16 @@ +name: Non-Tier Zero account with unconstrained delegation +guid: e7e9a927-3f34-42c7-b921-d8bcf626011e +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH (n:Base) + WHERE n.unconstraineddelegation = true + AND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero accounts with SID History of Tier Zero accounts.yml b/queries/Non-Tier Zero accounts with SID History of Tier Zero accounts.yml new file mode 100644 index 0000000..53e8ea9 --- /dev/null +++ b/queries/Non-Tier Zero accounts with SID History of Tier Zero accounts.yml @@ -0,0 +1,16 @@ +name: Non-Tier Zero accounts with SID History of Tier Zero accounts +guid: 59744dfe-9411-4daf-b342-1203dc62acd4 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Base)-[:HasSIDHistory]->(m:Base) + WHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0') + AND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero principals with BadSuccessor rights (no prerequisites check).yml b/queries/Non-Tier Zero principals with BadSuccessor rights (no prerequisites check).yml new file mode 100644 index 0000000..bb9ab79 --- /dev/null +++ b/queries/Non-Tier Zero principals with BadSuccessor rights (no prerequisites check).yml @@ -0,0 +1,18 @@ +name: Non-Tier Zero principals with BadSuccessor rights (no prerequisites check) +guid: 2b9fb71e-73ad-4061-a2df-40c7132b044d +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: Finds non-Tier Zero principals with BadSuccessor rights with no prerequisites check (DC2025 & KDC key). +query: |- + // Find OU control + MATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base) + // Exclude Tier Zero + WHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p LIMIT 1000 +note: +revision: 1 +resources: https://bsky.app/profile/specterops.io/post/3lpua65qeu22l +acknowledgement: Martin Sohn Christensen, @martinsohndk +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero principals with BadSuccessor rights (with prerequisites check).yml b/queries/Non-Tier Zero principals with BadSuccessor rights (with prerequisites check).yml new file mode 100644 index 0000000..c37df48 --- /dev/null +++ b/queries/Non-Tier Zero principals with BadSuccessor rights (with prerequisites check).yml @@ -0,0 +1,28 @@ +name: Non-Tier Zero principals with BadSuccessor rights (with prerequisites check) +guid: 74daaebe-6040-4f7a-9c9a-416faf73dcc3 +prebuilt: false +platform: 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 + MATCH (dc:Computer) + WHERE dc.isdc = true AND dc.operatingsystem CONTAINS '2025' + // Find gMSAs + MATCH (m:User) + WHERE m.gmsa = true + // Find OU control + MATCH p = (ou:OU)<-[:WriteDacl|Owns|GenericAll|WriteOwner]-(n:Base) + // Confirm domain has a 2025 DC + WHERE ou.domain = dc.domain + // Confirm domain KDC key + AND ou.domain = m.domain + // Exclude Tier Zero + AND NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p LIMIT 1000 +note: +revision: 1 +resources: https://bsky.app/profile/specterops.io/post/3lpua65qeu22l +acknowledgement: Martin Sohn Christensen, @martinsohndk +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-Tier Zero principals with control of AdminSDHolder.yml b/queries/Non-Tier Zero principals with control of AdminSDHolder.yml new file mode 100644 index 0000000..a47b7e5 --- /dev/null +++ b/queries/Non-Tier Zero principals with control of AdminSDHolder.yml @@ -0,0 +1,16 @@ +name: Non-Tier Zero principals with control of AdminSDHolder +guid: 4c1e0137-5b7f-48d8-bd09-9db7674bca61 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +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) + WHERE NOT ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND m.name STARTS WITH "ADMINSDHOLDER@" + RETURN p +note: +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 +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-default delegation on MicrosoftDNS container.yml b/queries/Non-default delegation on MicrosoftDNS container.yml new file mode 100644 index 0000000..f21e4d3 --- /dev/null +++ b/queries/Non-default delegation on MicrosoftDNS container.yml @@ -0,0 +1,18 @@ +name: Non-default delegation on MicrosoftDNS container +guid: 008792c0-4458-46a1-a10d-50cdaf95af1e +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Base)-[r]->(m:Container) + WHERE m.distinguishedname STARTS WITH "CN=MICROSOFTDNS,CN=SYSTEM,DC=" + AND NOT n.name STARTS WITH "DNSADMINS@" + AND NOT n.objectid =~ "-(512|544|519|9)$" + AND r.isacl + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-default members in Pre-Windows 2000 Compatible Access.yml b/queries/Non-default members in Pre-Windows 2000 Compatible Access.yml new file mode 100644 index 0000000..757620c --- /dev/null +++ b/queries/Non-default members in Pre-Windows 2000 Compatible Access.yml @@ -0,0 +1,18 @@ +name: Non-default members in Pre-Windows 2000 Compatible Access +guid: 091995b9-7254-473a-996f-6b8368d20431 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Group)-[:MemberOf]->(m:Group) + WHERE NOT n.objectid ENDS WITH "S-1-5-11" // Authenticated Users + AND NOT (n.objectid ENDS WITH "S-1-5-7" // Anonymous + AND NOT n.objectid ENDS WITH "S-1-1-0") // Everyone + AND m.objectid ENDS WITH "S-1-5-32-554" // Pre-Windows 2000 Compatible Access + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Non-default permissions on IssuancePolicy nodes.yml b/queries/Non-default permissions on IssuancePolicy nodes.yml new file mode 100644 index 0000000..5000a04 --- /dev/null +++ b/queries/Non-default permissions on IssuancePolicy nodes.yml @@ -0,0 +1,16 @@ +name: Non-default permissions on IssuancePolicy nodes +guid: b2280665-c91b-448c-8c0f-97d1f38b6f59 +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (s:Base)-[:GenericAll|GenericWrite|Owns|WriteOwner|WriteDacl]->(:IssuancePolicy) + WHERE NOT s.objectid ENDS WITH '-512' AND NOT s.objectid ENDS WITH '-519' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Object name conflict.yml b/queries/Object name conflict.yml new file mode 100644 index 0000000..12a117f --- /dev/null +++ b/queries/Object name conflict.yml @@ -0,0 +1,15 @@ +name: Object name conflict +guid: c561c4f8-ea45-453f-85a2-3fc2e20e7f8c +prebuilt: false +platform: 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) + WHERE n.distinguishedname CONTAINS 'CNF:' + RETURN n +note: +revision: 1 +resources: https://learn.microsoft.com/en-us/archive/technet-wiki/15435.active-directory-duplicate-object-name-resolution +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/On-Prem Users synced to Entra Users that Own Entra Objects.yml b/queries/On-Prem Users synced to Entra Users that Own Entra Objects.yml new file mode 100644 index 0000000..095e292 --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users that Own Entra Objects.yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users that Own Entra Objects +guid: 4baf1026-e64c-4e31-afeb-2090b8090130 +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwns]->(:AZBase) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/On-Prem Users synced to Entra Users with Azure RM Roles (direct).yml b/queries/On-Prem Users synced to Entra Users with Azure RM Roles (direct).yml new file mode 100644 index 0000000..e254257 --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users with Azure RM Roles (direct).yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users with Azure RM Roles (direct) +guid: 8569113b-e42e-49b0-a968-53bcf0ccd970 +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/On-Prem Users synced to Entra Users with Azure RM Roles (group delegated).yml b/queries/On-Prem Users synced to Entra Users with Azure RM Roles (group delegated).yml new file mode 100644 index 0000000..f400a7b --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users with Azure RM Roles (group delegated).yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users with Azure RM Roles (group delegated) +guid: e4f2eada-8a89-4ba9-89eb-abbee4efbc7a +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZOwner|AZUserAccessAdministrator|AZGetCertificates|AZGetKeys|AZGetSecrets|AZAvereContributor|AZKeyVaultContributor|AZContributor|AZVMAdminLogin|AZVMContributor|AZAKSContributor|AZAutomationContributor|AZLogicAppContributor|AZWebsiteContributor]->(:AZBase) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (direct).yml b/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (direct).yml new file mode 100644 index 0000000..c26aaf3 --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (direct).yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users with Entra Admin Roles (direct) +guid: de717635-d31f-4fbd-930b-b4dac0f22118 +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZHasRole]->(:AZRole) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated).yml b/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated).yml new file mode 100644 index 0000000..ff9310a --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated).yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users with Entra Admin Roles (group delegated) +guid: 609d648f-7fb8-42d3-ad99-626f9ce1f121 +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup)-[:AZHasRole]->(:AZRole) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/On-Prem Users synced to Entra Users with Entra Group Membership.yml b/queries/On-Prem Users synced to Entra Users with Entra Group Membership.yml new file mode 100644 index 0000000..2c7255d --- /dev/null +++ b/queries/On-Prem Users synced to Entra Users with Entra Group Membership.yml @@ -0,0 +1,17 @@ +name: On-Prem Users synced to Entra Users with Entra Group Membership +guid: edb575df-2048-4ef0-a0e4-168544a496e9 +prebuilt: true +platform: +- Active Directory +- Azure +category: Cross Platform Attack Paths +description: +query: |- + MATCH p = (:User)-[:SyncedToEntraUser]->(:AZUser)-[:AZMemberOf]->(:AZGroup) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/PKI hierarchy.yml b/queries/PKI hierarchy.yml new file mode 100644 index 0000000..d096694 --- /dev/null +++ b/queries/PKI hierarchy.yml @@ -0,0 +1,15 @@ +name: PKI hierarchy +guid: 928acc23-ee4c-40a5-bde7-64c05cc1491d +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p=()-[:HostsCAService|IssuedSignedBy|EnterpriseCAFor|RootCAFor|TrustedForNTAuth|NTAuthStoreFor*..]->(:Domain) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Paths from Domain Users to Tier Zero High Value targets.yml b/queries/Paths from Domain Users to Tier Zero High Value targets.yml new file mode 100644 index 0000000..3f31944 --- /dev/null +++ b/queries/Paths from Domain Users to Tier Zero High Value targets.yml @@ -0,0 +1,17 @@ +name: Paths from Domain Users to Tier Zero / High Value targets +guid: 977bec40-565c-40b8-90c8-e3e122c291cd +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=shortestPath((s:Group)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Base)) + WHERE s.objectid ENDS WITH '-513' AND s<>t + AND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Principal with SPN keyword.yml b/queries/Principal with SPN keyword.yml new file mode 100644 index 0000000..f7fdfbc --- /dev/null +++ b/queries/Principal with SPN keyword.yml @@ -0,0 +1,18 @@ +name: Principal with SPN keyword +guid: 38a9c4c9-3d70-453f-a017-cbfd35ed9917 +prebuilt: false +platform: 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) + WITH "KEYWORD" as SPNKeyword + MATCH (n:User) + WHERE ANY(keyword IN n.serviceprincipalnames WHERE toUpper(keyword) CONTAINS toUpper(SPNKeyword)) + RETURN n +note: +revision: 1 +resources: https://adsecurity.org/?page_id=183 +acknowledgement: Ryan, @haus3c +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Principals with DCSync privileges.yml b/queries/Principals with DCSync privileges.yml new file mode 100644 index 0000000..3fbf826 --- /dev/null +++ b/queries/Principals with DCSync privileges.yml @@ -0,0 +1,15 @@ +name: Principals with DCSync privileges +guid: 6e9beb8a-ad14-43de-bda1-644d174a5906 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(:Base)-[:DCSync|AllExtendedRights|GenericAll]->(:Domain) + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Principals with DES-only Kerberos authentication.yml b/queries/Principals with DES-only Kerberos authentication.yml new file mode 100644 index 0000000..31da9ed --- /dev/null +++ b/queries/Principals with DES-only Kerberos authentication.yml @@ -0,0 +1,16 @@ +name: Principals with DES-only Kerberos authentication +guid: d03ea1ef-70f0-439b-b1ef-d7f94ceb2af3 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE n.enabled = true + AND n.usedeskeyonly = true + RETURN n +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Principals with foreign domain group membership.yml b/queries/Principals with foreign domain group membership.yml new file mode 100644 index 0000000..776f3f6 --- /dev/null +++ b/queries/Principals with foreign domain group membership.yml @@ -0,0 +1,16 @@ +name: Principals with foreign domain group membership +guid: 8fb3214a-5a75-4ecd-b293-c121abd94b4b +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Base)-[:MemberOf]->(t:Group) + WHERE s.domainsid<>t.domainsid + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Principals with passwords stored using reversible encryption.yml b/queries/Principals with passwords stored using reversible encryption.yml new file mode 100644 index 0000000..51a679e --- /dev/null +++ b/queries/Principals with passwords stored using reversible encryption.yml @@ -0,0 +1,15 @@ +name: Principals with passwords stored using reversible encryption +guid: ab900835-b2b8-4674-87b4-8b5141e80439 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE n.encryptedtextpwdallowed = true + RETURN n +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Principals with weak supported Kerberos encryption types.yml b/queries/Principals with weak supported Kerberos encryption types.yml new file mode 100644 index 0000000..2d42f6f --- /dev/null +++ b/queries/Principals with weak supported Kerberos encryption types.yml @@ -0,0 +1,17 @@ +name: Principals with weak supported Kerberos encryption types +guid: ca329573-2157-41da-ab17-4d122c54b11d +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (u:Base) + WHERE 'DES-CBC-CRC' IN u.supportedencryptiontypes + OR 'DES-CBC-MD5' IN u.supportedencryptiontypes + OR 'RC4-HMAC-MD5' IN u.supportedencryptiontypes + RETURN u +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Public Key Services container.yml b/queries/Public Key Services container.yml new file mode 100644 index 0000000..e6217af --- /dev/null +++ b/queries/Public Key Services container.yml @@ -0,0 +1,16 @@ +name: Public Key Services container +guid: 07e94492-71aa-4665-ab8c-e7aec25906cd +prebuilt: true +platform: Active Directory +category: Active Directory Certificate Services +description: +query: |- + MATCH p = (c:Container)-[:Contains*..]->(:Base) + WHERE c.distinguishedname starts with 'CN=PUBLIC KEY SERVICES,CN=SERVICES,CN=CONFIGURATION,DC=' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Servers where Domain Users can RDP.yml b/queries/Servers where Domain Users can RDP.yml new file mode 100644 index 0000000..9613e54 --- /dev/null +++ b/queries/Servers where Domain Users can RDP.yml @@ -0,0 +1,16 @@ +name: Servers where Domain Users can RDP +guid: b9a330ae-1d89-44d4-8f74-9ca18e93eb92 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Group)-[:CanRDP]->(t:Computer) + WHERE s.objectid ENDS WITH '-513' AND toUpper(t.operatingsystem) CONTAINS 'SERVER' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Sessions across trusts.yml b/queries/Sessions across trusts.yml new file mode 100644 index 0000000..76e010b --- /dev/null +++ b/queries/Sessions across trusts.yml @@ -0,0 +1,17 @@ +name: Sessions across trusts +guid: aea7ac64-1f51-407b-b0ee-19fd30075794 +prebuilt: false +platform: 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) + WHERE trustedDomainPrincipal.domainsid <> trustingDomainPrincipal.domainsid + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgement: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Shortest paths from Azure Applications to Tier Zero High Value targets.yml b/queries/Shortest paths from Azure Applications to Tier Zero High Value targets.yml new file mode 100644 index 0000000..551ebae --- /dev/null +++ b/queries/Shortest paths from Azure Applications to Tier Zero High Value targets.yml @@ -0,0 +1,16 @@ +name: Shortest paths from Azure Applications to Tier Zero / High Value targets +guid: 60ff7c58-a98e-4bc1-9e32-8378d2db0c43 +prebuilt: true +platform: Azure +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:AZApp)-[:AZAvereContributor|AZContributor|AZGetCertificates|AZGetKeys|AZGetSecrets|AZHasRole|AZMemberOf|AZOwner|AZRunsAs|AZVMContributor|AZAutomationContributor|AZKeyVaultContributor|AZVMAdminLogin|AZAddMembers|AZAddSecret|AZExecuteCommand|AZGlobalAdmin|AZPrivilegedAuthAdmin|AZGrant|AZGrantSelf|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZOwns|AZCloudAppAdmin|AZAppAdmin|AZAddOwner|AZManagedIdentity|AZAKSContributor|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributor|AZMGAddMember|AZMGAddOwner|AZMGAddSecret|AZMGGrantAppRoles|AZMGGrantRole|SyncedToADUser|AZRoleEligible|AZContains*1..]->(t:AZBase)) + WHERE ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') AND s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths from Domain Users to Tier Zero High Value targets.yml b/queries/Shortest paths from Domain Users to Tier Zero High Value targets.yml new file mode 100644 index 0000000..6911caf --- /dev/null +++ b/queries/Shortest paths from Domain Users to Tier Zero High Value targets.yml @@ -0,0 +1,17 @@ +name: Shortest paths from Domain Users to Tier Zero / High Value targets +guid: 469dc0f3-71b8-41b0-a03b-b4af7874665d +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:Group)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Base)) + WHERE s.objectid ENDS WITH '-513' AND s<>t + AND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p + LIMIT 1000 +note: +revision: 1 +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 new file mode 100644 index 0000000..abe9454 --- /dev/null +++ b/queries/Shortest paths from Entra Users to Tier Zero High Value targets.yml @@ -0,0 +1,17 @@ +name: Shortest paths from Entra Users to Tier Zero / High Value targets +guid: 58089b28-54e0-4fd2-bf66-3db480b00e2f +prebuilt: true +platform: Azure +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:AZUser)-[:AZAvereContributor|AZContributor|AZGetCertificates|AZGetKeys|AZGetSecrets|AZHasRole|AZMemberOf|AZOwner|AZRunsAs|AZVMContributor|AZAutomationContributor|AZKeyVaultContributor|AZVMAdminLogin|AZAddMembers|AZAddSecret|AZExecuteCommand|AZGlobalAdmin|AZPrivilegedAuthAdmin|AZGrant|AZGrantSelf|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZOwns|AZCloudAppAdmin|AZAppAdmin|AZAddOwner|AZManagedIdentity|AZAKSContributor|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributor|AZMGAddMember|AZMGAddOwner|AZMGAddSecret|AZMGGrantAppRoles|AZMGGrantRole|SyncedToADUser|AZRoleEligible|AZContains*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') + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths from Owned objects to Tier Zero.yml b/queries/Shortest paths from Owned objects to Tier Zero.yml new file mode 100644 index 0000000..9b4d700 --- /dev/null +++ b/queries/Shortest paths from Owned objects to Tier Zero.yml @@ -0,0 +1,18 @@ +name: Shortest paths from Owned objects to Tier Zero +guid: dfaa8e8f-2c79-4e92-a291-b1347f6e83b0 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + // MANY TO MANY SHORTEST PATH QUERIES USE EXCESSIVE SYSTEM RESOURCES AND TYPICALLY WILL NOT COMPLETE + MATCH p=shortestPath((s:Tag_Owned)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Base)) + WHERE s<>t + AND ((t:Tag_Tier_Zero) OR COALESCE(t.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths from Owned objects.yml b/queries/Shortest paths from Owned objects.yml new file mode 100644 index 0000000..d1057ba --- /dev/null +++ b/queries/Shortest paths from Owned objects.yml @@ -0,0 +1,17 @@ +name: Shortest paths from Owned objects +guid: e370a01d-c129-4f19-b88d-9479cbe00028 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:Base)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Base)) + WHERE (s:Tag_Owned) + AND s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to Azure Subscriptions.yml b/queries/Shortest paths to Azure Subscriptions.yml new file mode 100644 index 0000000..4f770e4 --- /dev/null +++ b/queries/Shortest paths to Azure Subscriptions.yml @@ -0,0 +1,16 @@ +name: Shortest paths to Azure Subscriptions +guid: 4785b305-c101-461c-80fc-3fb3ff67a8ce +prebuilt: true +platform: Azure +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:AZBase)-[:AZAvereContributor|AZContributor|AZGetCertificates|AZGetKeys|AZGetSecrets|AZHasRole|AZMemberOf|AZOwner|AZRunsAs|AZVMContributor|AZAutomationContributor|AZKeyVaultContributor|AZVMAdminLogin|AZAddMembers|AZAddSecret|AZExecuteCommand|AZGlobalAdmin|AZPrivilegedAuthAdmin|AZGrant|AZGrantSelf|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZOwns|AZCloudAppAdmin|AZAppAdmin|AZAddOwner|AZManagedIdentity|AZAKSContributor|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributor|AZMGAddMember|AZMGAddOwner|AZMGAddSecret|AZMGGrantAppRoles|AZMGGrantRole|SyncedToADUser|AZRoleEligible|AZContains*1..]->(t:AZSubscription)) + WHERE s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to Domain Admins from Kerberoastable users.yml b/queries/Shortest paths to Domain Admins from Kerberoastable users.yml new file mode 100644 index 0000000..a506e65 --- /dev/null +++ b/queries/Shortest paths to Domain Admins from Kerberoastable users.yml @@ -0,0 +1,21 @@ +name: Shortest paths to Domain Admins from Kerberoastable users +guid: bd163361-1e05-47c7-908b-962aef251535 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:User)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Group)) + WHERE s.hasspn=true + AND s.enabled = true + AND NOT s.objectid ENDS WITH '-502' + AND NOT COALESCE(s.gmsa, false) = true + AND NOT COALESCE(s.msa, false) = true + AND t.objectid ENDS WITH '-512' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to Domain Admins.yml b/queries/Shortest paths to Domain Admins.yml new file mode 100644 index 0000000..cd9786f --- /dev/null +++ b/queries/Shortest paths to Domain Admins.yml @@ -0,0 +1,16 @@ +name: Shortest paths to Domain Admins +guid: f40cb34b-5ec7-44bc-9aa8-a200a4a41f22 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((t:Group)<-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]-(s:Base)) + WHERE t.objectid ENDS WITH '-512' AND s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to Tier Zero High Value targets.yml b/queries/Shortest paths to Tier Zero High Value targets.yml new file mode 100644 index 0000000..008462b --- /dev/null +++ b/queries/Shortest paths to Tier Zero High Value targets.yml @@ -0,0 +1,16 @@ +name: Shortest paths to Tier Zero / High Value targets +guid: 237aac58-8641-4703-a9f7-001d69546fd8 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Tag_Tier_Zero)) + WHERE s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to privileged roles.yml b/queries/Shortest paths to privileged roles.yml new file mode 100644 index 0000000..d402819 --- /dev/null +++ b/queries/Shortest paths to privileged roles.yml @@ -0,0 +1,16 @@ +name: Shortest paths to privileged roles +guid: 3dc73dd8-4873-4aeb-a88f-56a58c77f512 +prebuilt: true +platform: Azure +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s:AZBase)-[:AZAvereContributor|AZContributor|AZGetCertificates|AZGetKeys|AZGetSecrets|AZHasRole|AZMemberOf|AZOwner|AZRunsAs|AZVMContributor|AZAutomationContributor|AZKeyVaultContributor|AZVMAdminLogin|AZAddMembers|AZAddSecret|AZExecuteCommand|AZGlobalAdmin|AZPrivilegedAuthAdmin|AZGrant|AZGrantSelf|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZOwns|AZCloudAppAdmin|AZAppAdmin|AZAddOwner|AZManagedIdentity|AZAKSContributor|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributor|AZMGAddMember|AZMGAddOwner|AZMGAddSecret|AZMGGrantAppRoles|AZMGGrantRole|SyncedToADUser|AZRoleEligible|AZContains*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 + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Shortest paths to systems trusted for unconstrained delegation.yml b/queries/Shortest paths to systems trusted for unconstrained delegation.yml new file mode 100644 index 0000000..6b0c80e --- /dev/null +++ b/queries/Shortest paths to systems trusted for unconstrained delegation.yml @@ -0,0 +1,16 @@ +name: Shortest paths to systems trusted for unconstrained delegation +guid: 16a9e47b-45f8-4514-b409-771bb5186142 +prebuilt: true +platform: Active Directory +category: Shortest Paths +description: +query: |- + MATCH p=shortestPath((s)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl|MemberOf|ForceChangePassword|AllExtendedRights|AddMember|HasSession|GPLink|AllowedToDelegate|CoerceToTGT|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM|HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword|SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword|WriteAccountRestrictions|WriteGPLink|GoldenCert|ADCSESC1|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC6b|ADCSESC9a|ADCSESC9b|ADCSESC10a|ADCSESC10b|ADCSESC13|SyncedToEntraUser|CoerceAndRelayNTLMToSMB|CoerceAndRelayNTLMToADCS|WriteOwnerLimitedRights|OwnsLimitedRights|CoerceAndRelayNTLMToLDAP|CoerceAndRelayNTLMToLDAPS|Contains|DCFor|SameForestTrust|SpoofSIDHistory|AbuseTGTDelegation*1..]->(t:Computer)) + WHERE t.unconstraineddelegation = true AND s<>t + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Smart card accounts with passwords not rotated in over 1 year.yml b/queries/Smart card accounts with passwords not rotated in over 1 year.yml new file mode 100644 index 0000000..4ee2ad1 --- /dev/null +++ b/queries/Smart card accounts with passwords not rotated in over 1 year.yml @@ -0,0 +1,17 @@ +name: Smart card accounts with passwords not rotated in over 1 year +guid: 7e56f2e7-79c3-4f0d-aa3e-14cf3de7ab73 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE n.pwdlastset < (datetime().epochseconds - (365 * 86400)) + AND n.enabled = true + AND n.smartcardrequired = true + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero AD principals synchronized with Entra ID.yml b/queries/Tier Zero AD principals synchronized with Entra ID.yml new file mode 100644 index 0000000..89c7ec6 --- /dev/null +++ b/queries/Tier Zero AD principals synchronized with Entra ID.yml @@ -0,0 +1,20 @@ +name: Tier Zero AD principals synchronized with Entra ID +guid: a8b6ec67-21aa-4dd2-8906-47bb81bf5262 +prebuilt: true +platform: Azure +category: Azure Hygiene +description: +query: |- + MATCH (ENTRA:AZBase) + MATCH (AD:Base) + WHERE ((AD:Tag_Tier_Zero) OR COALESCE(AD.system_tags, '') CONTAINS 'admin_tier_0') + AND ENTRA.onpremsyncenabled = true + AND ENTRA.onpremid = AD.objectid + RETURN ENTRA + // Replace 'RETURN ENTRA' with 'RETURN AD' to see the corresponding AD principals + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Tier Zero High Value enabled users not requiring smart card authentication.yml b/queries/Tier Zero High Value enabled users not requiring smart card authentication.yml new file mode 100644 index 0000000..fd907e6 --- /dev/null +++ b/queries/Tier Zero High Value enabled users not requiring smart card authentication.yml @@ -0,0 +1,20 @@ +name: Tier Zero / High Value enabled users not requiring smart card authentication +guid: 867f9f17-c149-4c4b-ad84-9a807622ff8c +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (u:User) + WHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0') + AND u.enabled = true + AND u.smartcardrequired = false + AND NOT u.name STARTS WITH 'MSOL_' // Removes false positive, Entra sync + AND NOT u.name STARTS WITH 'PROVAGENTGMSA' // Removes false positive, Entra sync + AND NOT u.name STARTS WITH 'ADSYNCMSA_' // Removes false positive, Entra sync + RETURN u +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Tier Zero High Value external Entra ID users.yml b/queries/Tier Zero High Value external Entra ID users.yml new file mode 100644 index 0000000..200134b --- /dev/null +++ b/queries/Tier Zero High Value external Entra ID users.yml @@ -0,0 +1,17 @@ +name: Tier Zero / High Value external Entra ID users +guid: 20e07417-d286-4dca-a962-568f2b262f65 +prebuilt: true +platform: Azure +category: Azure Hygiene +description: +query: |- + MATCH (n:AZUser) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.name CONTAINS '#EXT#@' + RETURN n + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Tier Zero High Value users with non-expiring passwords.yml b/queries/Tier Zero High Value users with non-expiring passwords.yml new file mode 100644 index 0000000..b03a263 --- /dev/null +++ b/queries/Tier Zero High Value users with non-expiring passwords.yml @@ -0,0 +1,17 @@ +name: Tier Zero / High Value users with non-expiring passwords +guid: 4eca1b69-00a2-48a0-abb3-b94ea647cf6b +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (u:User) + WHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0') AND u.enabled = true + AND u.pwdneverexpires = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Tier Zero accounts not members of Denied RODC Password Replication Group.yml b/queries/Tier Zero accounts not members of Denied RODC Password Replication Group.yml new file mode 100644 index 0000000..6264980 --- /dev/null +++ b/queries/Tier Zero accounts not members of Denied RODC Password Replication Group.yml @@ -0,0 +1,21 @@ +name: Tier Zero accounts not members of Denied RODC Password Replication Group +guid: e9613406-e346-410b-a033-690a6cf0c708 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND (n:User or n:Computer) + WITH n + OPTIONAL MATCH (n)-[:MemberOf*1..]->(m:Group) + WHERE m.objectid ENDS WITH '-519' + WITH n, m + WHERE m IS NULL + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero accounts that can be delegated.yml b/queries/Tier Zero accounts that can be delegated.yml new file mode 100644 index 0000000..08bb0a7 --- /dev/null +++ b/queries/Tier Zero accounts that can be delegated.yml @@ -0,0 +1,21 @@ +name: Tier Zero accounts that can be delegated +guid: 4316eaf1-6af0-4879-8f55-ac2633a711c3 +prebuilt: false +platform: Active Directory +category: Kerberos Interaction +description: +query: |- + MATCH (m:Base) + WHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0') + AND m.enabled = true + AND m.sensitive = false + OPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base) + WHERE g.objectid ENDS WITH '-525' + WITH m, COLLECT(n) AS matchingNs + WHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid) + RETURN m +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers at risk of constrained delegation.yml b/queries/Tier Zero computers at risk of constrained delegation.yml new file mode 100644 index 0000000..8b52703 --- /dev/null +++ b/queries/Tier Zero computers at risk of constrained delegation.yml @@ -0,0 +1,15 @@ +name: Tier Zero computers at risk of constrained delegation +guid: 8641e593-f2f2-48ba-bd45-fbc86e9f632a +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p = (n:Computer)<-[:AllowedToDelegate]-(:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers at risk of resource-based constrained delegation.yml b/queries/Tier Zero computers at risk of resource-based constrained delegation.yml new file mode 100644 index 0000000..313944e --- /dev/null +++ b/queries/Tier Zero computers at risk of resource-based constrained delegation.yml @@ -0,0 +1,15 @@ +name: Tier Zero computers at risk of resource-based constrained delegation +guid: 4dc97cf4-3c03-4fe6-8a8b-4f665c67e1e5 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p = (n:Computer)<-[:AllowedToAct]-(:Base) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers not owned by Tier Zero.yml b/queries/Tier Zero computers not owned by Tier Zero.yml new file mode 100644 index 0000000..a81257f --- /dev/null +++ b/queries/Tier Zero computers not owned by Tier Zero.yml @@ -0,0 +1,15 @@ +name: Tier Zero computers not owned by Tier Zero +guid: 99d29ded-223a-442b-a0e0-f8b5694c6441 +prebuilt: false +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(n:Base)-[:Owns]->(:Computer) + WHERE NOT coalesce(n.system_tags, "") CONTAINS "admin_tier_0" + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers not requiring inbound SMB signing.yml b/queries/Tier Zero computers not requiring inbound SMB signing.yml new file mode 100644 index 0000000..7ed91b5 --- /dev/null +++ b/queries/Tier Zero computers not requiring inbound SMB signing.yml @@ -0,0 +1,16 @@ +name: Tier Zero omputers not requiring inbound SMB signing +guid: 13485477-f026-4b1f-906d-4f2e37364ba4 +prebuilt: false +platform: Active Directory +category: NTLM Relay Attacks +description: +query: |- + MATCH (n:Computer) + WHERE n.smbsigning = False + AND ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers with passwords older than the default maximum password age.yml b/queries/Tier Zero computers with passwords older than the default maximum password age.yml new file mode 100644 index 0000000..ad2febb --- /dev/null +++ b/queries/Tier Zero computers with passwords older than the default maximum password age.yml @@ -0,0 +1,18 @@ +name: Tier Zero computers with passwords older than the default maximum password age +guid: b6d6d0bf-130e-4719-996b-adc29bba36e9 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:Computer) + WHERE n.enabled = true + AND n.whencreated < (datetime().epochseconds - (60 * 3 * 86400)) + AND n.pwdlastset < (datetime().epochseconds - (60 * 3 * 86400)) + AND coalesce(n.system_tags, "") CONTAINS "admin_tier_0" + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers with the WebClient running.yml b/queries/Tier Zero computers with the WebClient running.yml new file mode 100644 index 0000000..ba0ec58 --- /dev/null +++ b/queries/Tier Zero computers with the WebClient running.yml @@ -0,0 +1,16 @@ +name: Tier Zero computers with the WebClient running +guid: 27a6f917-8ed4-4e2e-9b38-41a4b6de1b14 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (c:Computer) + WHERE c.webclientrunning = True + AND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0') + RETURN c LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero computers with unsupported operating systems.yml b/queries/Tier Zero computers with unsupported operating systems.yml new file mode 100644 index 0000000..db861e1 --- /dev/null +++ b/queries/Tier Zero computers with unsupported operating systems.yml @@ -0,0 +1,17 @@ +name: Tier Zero computers with unsupported operating systems +guid: a87b558c-5746-4a90-9f83-c86e7b924a52 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (c:Computer) + WHERE c.operatingsystem =~ '(?i).*Windows.* (2000|2003|2008|2012|xp|vista|7|8|me|nt).*' + AND ((c:Tag_Tier_Zero) OR COALESCE(c.system_tags, '') CONTAINS 'admin_tier_0') + RETURN c + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero users not member of Protected Users.yml b/queries/Tier Zero users not member of Protected Users.yml new file mode 100644 index 0000000..ccddd5d --- /dev/null +++ b/queries/Tier Zero users not member of Protected Users.yml @@ -0,0 +1,19 @@ +name: Tier Zero users not member of Protected Users +guid: 543eb01d-9fa3-4b8f-a936-b46bbfdaa2ae +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (m:User) + WHERE ((m:Tag_Tier_Zero) OR COALESCE(m.system_tags, '') CONTAINS 'admin_tier_0') + OPTIONAL MATCH (g:Group)<-[:MemberOf*1..]-(n:Base) + WHERE g.objectid ENDS WITH '-525' + WITH m, COLLECT(n) AS matchingNs + WHERE NONE(n IN matchingNs WHERE n.objectid = m.objectid) + RETURN m +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero users with email.yml b/queries/Tier Zero users with email.yml new file mode 100644 index 0000000..c6c207b --- /dev/null +++ b/queries/Tier Zero users with email.yml @@ -0,0 +1,30 @@ +name: Tier Zero users with email +guid: 9654c0d4-f1e8-4393-a2d1-53a5554a9de8 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: Tier Zero accounts with email access have an increased attack surface. +query: |- + MATCH (n) + WHERE ((n:Tag_Tier_Zero) OR COALESCE(n.system_tags, '') CONTAINS 'admin_tier_0') + AND n.email <> "" + AND n.enabled = true + AND NOT toUpper(n.email) ENDS WITH ".ONMICROSOFT.COM" + AND NOT ( + (toUpper(n.email) STARTS WITH "HEALTHMAILBOX" + OR toUpper(n.email) STARTS WITH "MSEXCHDISCOVERYMAILBOX" + OR toUpper(n.email) STARTS WITH "MSEXCHDISCOVERY" + OR toUpper(n.email) STARTS WITH "MSEXCHAPPROVAL" + OR toUpper(n.email) STARTS WITH "FEDERATEDEMAIL" + OR toUpper(n.email) STARTS WITH "SYSTEMMAILBOX" + OR toUpper(n.email) STARTS WITH "MIGRATION.") + AND + (n.name STARTS WITH "SM_" + OR n.name STARTS WITH "HEALTHMAILBOX") + ) + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Tier Zero users with passwords not rotated in over 1 year.yml b/queries/Tier Zero users with passwords not rotated in over 1 year.yml new file mode 100644 index 0000000..c3b898b --- /dev/null +++ b/queries/Tier Zero users with passwords not rotated in over 1 year.yml @@ -0,0 +1,19 @@ +name: Tier Zero users with passwords not rotated in over 1 year +guid: 5e0d69b1-37d1-43ae-ac5d-f297f312fab5 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 365 as days_since_change + MATCH (u:User) + WHERE ((u:Tag_Tier_Zero) OR COALESCE(u.system_tags, '') CONTAINS 'admin_tier_0') + AND u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400)) + AND NOT u.pwdlastset IN [-1.0, 0.0] + RETURN u + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Trace ACE inheritance.yml b/queries/Trace ACE inheritance.yml new file mode 100644 index 0000000..ec6909f --- /dev/null +++ b/queries/Trace ACE inheritance.yml @@ -0,0 +1,19 @@ +name: Trace ACE inheritance +guid: 8c5454df-3ae8-412c-b271-3c4c55df7141 +prebuilt: false +platform: 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 + // Replace 'GenericAll' with the specific edge you're tracing + WITH "INSERT_OBJECT_ID" as OID + MATCH p=()-[:GenericAll {isacl:true,isinherited:false}]->()-[:Contains*1..]->(:Base{objectid:OID}) + WHERE NONE(ou in NODES(p) WHERE ou:OU AND ou.isaclprotected IS NOT NULL) + RETURN p +note: +revision: 1 +resources: +acknowledgement: Walter.Legowski, @SadProcessor +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Unresolved SID with outbound control.yml b/queries/Unresolved SID with outbound control.yml new file mode 100644 index 0000000..a20402d --- /dev/null +++ b/queries/Unresolved SID with outbound control.yml @@ -0,0 +1,17 @@ +name: Unresolved SID with outbound control +guid: 4e8429f9-cba2-41e9-bac6-0c42f96b2c57 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:Base)-[r]->(:Base) + WHERE r.isacl + AND n.name CONTAINS "S-1-5-21-" // Unresolved SID + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Usage of built-in domain Administrator account.yml b/queries/Usage of built-in domain Administrator account.yml new file mode 100644 index 0000000..e3b4272 --- /dev/null +++ b/queries/Usage of built-in domain Administrator account.yml @@ -0,0 +1,20 @@ +name: Usage of built-in domain Administrator account +guid: 35b1206f-871b-44aa-a601-c5258060dfcf +prebuilt: false +platform: Active Directory +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) + WHERE n.objectid ENDS WITH "-500" + AND ( + n.lastlogontimestamp > (datetime().epochseconds - (60 * 86400)) OR + n.lastlogon > (datetime().epochseconds - (60 * 86400)) + ) + AND NOT n.whencreated > (datetime().epochseconds - (60 * 86400)) + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Users which do not require password to authenticate.yml b/queries/Users which do not require password to authenticate.yml new file mode 100644 index 0000000..d54acb2 --- /dev/null +++ b/queries/Users which do not require password to authenticate.yml @@ -0,0 +1,16 @@ +name: Users which do not require password to authenticate +guid: 23bdc2ad-6739-4b2b-85d3-258e3f424eb2 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (u:User) + WHERE u.passwordnotreqd = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Users with logon scripts stored in a trusted domain.yml b/queries/Users with logon scripts stored in a trusted domain.yml new file mode 100644 index 0000000..2fc4a45 --- /dev/null +++ b/queries/Users with logon scripts stored in a trusted domain.yml @@ -0,0 +1,18 @@ +name: Users with logon scripts stored in a trusted domain +guid: 8d94d3f3-3d53-4939-a206-3c0a4dd3f646 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (n:User) + WHERE n.logonscript IS NOT NULL + MATCH (d:Domain)-[:TrustedBy]->(:Domain)-[:Contains*1..]->(n) + WITH n,last(split(d.name, '@')) AS domain + WHERE toUpper(n.logonscript) STARTS WITH ("\\\\" + domain + "\\") + RETURN n +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Users with non-default Primary Group membership.yml b/queries/Users with non-default Primary Group membership.yml new file mode 100644 index 0000000..57df438 --- /dev/null +++ b/queries/Users with non-default Primary Group membership.yml @@ -0,0 +1,19 @@ +name: Users with non-default Primary Group membership +guid: 93890f88-df2c-4167-a945-a53961d08d00 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH p=(n:User)-[r:MemberOf]->(g:Group) + WHERE NOT g.objectid ENDS WITH "-513" // Domain Users + AND r.isprimarygroup = true + AND NOT n.objectid ENDS WITH "-501" // Guests account, as it has primaryGroup to Guests + AND (n.gmsa IS NULL OR n.gmsa = false) // Not gMSA, as it has primaryGroup to Domain Computers + AND (n.msa IS NULL OR n.msa = false) // Not MSA, as it has primaryGroup to Domain Computers + RETURN p +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Users with non-expiring passwords.yml b/queries/Users with non-expiring passwords.yml new file mode 100644 index 0000000..697cf8c --- /dev/null +++ b/queries/Users with non-expiring passwords.yml @@ -0,0 +1,17 @@ +name: Users with non-expiring passwords +guid: 212c2a98-53d9-4dfa-b177-42c601452dd1 +prebuilt: false +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + MATCH (u:User) + WHERE u.enabled = true + AND u.pwdneverexpires = true + RETURN u + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: Martin Sohn Christensen, @martinsohndk + diff --git a/queries/Users with passwords not rotated in over 1 year.yml b/queries/Users with passwords not rotated in over 1 year.yml new file mode 100644 index 0000000..c9b8c23 --- /dev/null +++ b/queries/Users with passwords not rotated in over 1 year.yml @@ -0,0 +1,18 @@ +name: Users with passwords not rotated in over 1 year +guid: be70d1bd-b7eb-40b0-971c-eefc50eca032 +prebuilt: true +platform: Active Directory +category: Active Directory Hygiene +description: +query: |- + WITH 365 as days_since_change + MATCH (u:User) + WHERE u.pwdlastset < (datetime().epochseconds - (days_since_change * 86400)) + AND NOT u.pwdlastset IN [-1.0, 0.0] + RETURN u + LIMIT 100 +note: +revision: 1 +resources: +acknowledgements: + diff --git a/queries/Workstations where Domain Users can RDP.yml b/queries/Workstations where Domain Users can RDP.yml new file mode 100644 index 0000000..53f51b2 --- /dev/null +++ b/queries/Workstations where Domain Users can RDP.yml @@ -0,0 +1,16 @@ +name: Workstations where Domain Users can RDP +guid: 9486e0e6-2617-4595-b969-cf57ca21fc86 +prebuilt: true +platform: Active Directory +category: Dangerous Privileges +description: +query: |- + MATCH p=(s:Group)-[:CanRDP]->(t:Computer) + WHERE s.objectid ENDS WITH '-513' AND NOT toUpper(t.operatingsystem) CONTAINS 'SERVER' + RETURN p + LIMIT 1000 +note: +revision: 1 +resources: +acknowledgements: +