[
  {
    "path": "README.md",
    "content": "\nThis repo contains a [customqueries.json](https://raw.githubusercontent.com/awsmhacks/awsmBloodhoundCustomQueries/master/customqueries.json) file with several examples you can use and/or modify.  \nFurther down in the [Cypher](#cypher-queries-neo4j-web-interface)  section I have several queries that can be used in the neo4j interface.  \n\nI didnt write most of these, this is a culmination of items gathered from various gists, githubs, and threads in the #cypher-queries bloodhound channel.    \n \n## Custom Queries (Bloodhound UI)  \n\nBloodhound's UI allows you to create 'custom queries' to make repeating often used queries easy.  \nThese are stored in a customqueries.json file.  \n- Generally these are queries that return paths  \n\nSome queries that were removed from the default list, as well as other useful queries, can be found in the [customqueries.json](https://raw.githubusercontent.com/awsmhacks/awsmBloodhoundCustomQueries/master/customqueries.json) file.   \n  \nCopy/paste the entire thing into your own customqueries file and hit refresh next to \"Custom Queries\" to see them show up in the bloodhound UI.    \n\n#### The customqueries file locations by OS (in default setup):   \n\nWindows : %USERPROFILE%\\AppData\\Roaming\\bloodhound\\customqueries.json  \nOSX: ~/Library/Application Support/bloodhound/customqueries.json  \nNIX: ~/.config/bloodhound/customqueries.json  \n\n-----------------------------------------------------------------------\n\n## Cypher Queries (Neo4j Web Interface) \n  \nThe CYPHER section are queries you would put into the neo4j interface and get results in tables.   \n- Generally these queries are used when you want to return lists or get percentages for report things  \n  \n-----------------------------------------------------------------------\n                    ######     ##    ##    ########     ##     ##    ########    ########  \n                   ##    ##     ##  ##     ##     ##    ##     ##    ##          ##     ## \n                   ##            ####      ##     ##    ##     ##    ##          ##     ## \n                   ##             ##       ########     #########    ######      ########  \n                   ##             ##       ##           ##     ##    ##          ##   ##   \n                   ##    ##       ##       ##           ##     ##    ##          ##    ##  \n                    ######        ##       ##           ##     ##    ########    ##     ## \n                                                               \n-----------------------------------------------------------------------\n\n\nThese are mostly for running in the web interface of neo4j. ~ http://localhost:7474  \nSome need to be modified based on the domain/user/group you are looking for  \ni.e  change \"EXAMPLE.COM\" or \"g.name contains \"DOMAIN ADMINS\"\"\n  \n\n-----------------------------------------------------------------------                                                              \nT.o.C\n\n1. [Get a count of computers that do not have admins](#1-get-a-count-of-computers-that-do-not-have-admins)  \n2. [Get the names of computers without admins, sorted in alphabetical order](#2-get-the-names-of-computers-without-admins-sorted-in-alphabetical-order)  \n3. [Return a list of users who have admin rights on at least one system either explicitly or through group membership](#3-return-a-list-of-users-who-have-admin-rights-on-at-least-one-system-either-explicitly-or-through-group-membership)  \n4. [Return username and number of computers that username is admin for, for top N users](#4-return-username-and-number-of-computers-that-username-is-admin-for-for-top-n-users)  \n5. [Show all users that are administrator on more than one machine](#5-show-all-users-that-are-administrator-on-more-than-one-machine)  \n6. [Show all users that are administrative on at least one machine, ranked by the number of machines they are admin on.](#6-show-all-users-that-are-administrative-on-at-least-one-machine-ranked-by-the-number-of-machines-they-are-admin-on)  \n7. [This will return cross domain 'HasSession' relationships](#7-this-will-return-cross-domain-hassession-relationships)  \n8. [Find all other Rights Domain Users shouldn't have](#8-find-all-other-rights-domain-users-shouldnt-have)  \n9. [Show Kerberoastable high value targets](#9-show-kerberoastable-high-value-targets)  \n10. [Show computers where Domain Admins are logged in](#10-show-computers-where-domain-admins-are-logged-in)  \n11. [Show groups with most localAdmin](#11-show-groups-with-most-localadmin)  \n12. [List of unique users with a path (no \"GetChanges\" path) to a Group tagged as \"highvalue\"](#12-list-of-unique-users-with-a-path-no-getchanges-path-to-a-group-tagged-as-highvalue)  \n13. [Return all users which can rdp to any system, if they belong to adm or svr accounts](#13-return-all-users-which-can-rdp-to-any-system-if-they-belong-to-adm-or-svr-accounts)  \n14. [Show the number of _users_ that have admin rights on each computer, in descending order](#14-show-the-number-of-users-that-have-admin-rights-on-each-computer-in-descending-order)  \n15. [Stats percentage of enabled users that have a path to a high value group](#15-stats-percentage-of-enabled-users-that-have-a-path-to-a-high-value-group)  \n16. [Shows machines that allow delegation that arent DCs](#16-shows-machines-that-allow-delegation-that-arent-dcs)  \n17. [Groups with most local admin](#17-groups-with-most-local-admin)  \n18. [Find principles with DCSync rights](#18-find-principles-with-dcsync-rights)  \n19. [Find all Windows 7 computers](#19-find-all-windows-7-computers)  \n20. [Find every user object where the \"userpassword\" attribute is populated. Neo4j web console only.](#20-find-every-user-object-where-the-userpassword-attribute-is-populated-neo4j-web-console-only)  \n21. [Find every user that doesn't require kerberos pre-authentication. Neo4j web console only.](#21-find-every-user-that-doesnt-require-kerberos-pre-authentication-neo4j-web-console-only)  \n22. [Return any group where the name of the group contains the string \"SQL\" followed by the string \"ADMIN\". This will match \"SQL ADMINS\" and will also match \"SQL 2017 ADMINS\".](#22-return-any-group-where-the-name-of-the-group-contains-the-string-sql-followed-by-the-string-admin-this-will-match-sql-admins-and-will-also-match-sql-2017-admins-neo4j-web-console-only)  \n23. [Find every OU that contains the string \"CITRIX\".](#23-find-every-ou-that-contains-the-string-citrix)  \n24. [Find all computers with sessions from users of a different domain (Looking for cross-domain compromise opportunities). Neo4j web console only.](#24-find-all-computers-with-sessions-from-users-of-a-different-domain-looking-for-cross-domain-compromise-opportunities-neo4j-web-console-only)  \n25. [Find all users trusted to perform constrained delegation, return in order of the number of target computers. Neo4j web console only.](#25-find-all-users-trusted-to-perform-constrained-delegation-return-in-order-of-the-number-of-target-computers-neo4j-web-console-only)  \n26. [Return each OU in the database in order of the number of computers in that OU. Neo4j web console only.](#26-return-each-ou-in-the-database-in-order-of-the-number-of-computers-in-that-ou-neo4j-web-console-only)  \n27. [Return the name of every computer in the database where at least one SPN for the computer contains the string \"MSSQL\". Neo4j web console only.](#27-return-the-name-of-every-computer-in-the-database-where-at-least-one-spn-for-the-computer-contains-the-string-mssql-neo4j-web-console-only)  \n28. [Find groups with both users and computers that belong to the group. Neo4j web console only.](#28-find-groups-with-both-users-and-computers-that-belong-to-the-group-neo4j-web-console-only)  \n29. [Return each OU in the database that contains a Windows Server computer. Return rows where the columns are the name of the OU, the name of the computer, and the operating system](#29-return-each-ou-in-the-database-that-contains-a-windows-server-computer-return-rows-where-the-columns-are-the-name-of-the-ou-the-name-of-the-computer-and-the-operating-system-of-the-computer-neo4j-web-console-only)  \n30. [Find any computer that is NOT a domain controller that is trusted to perform unconstrained delegation. Neo4j web console only.](#30-find-any-computer-that-is-not-a-domain-controller-that-is-trusted-to-perform-unconstrained-delegation-neo4j-web-console-only)  \n31. [Find every instance of a computer account having local admin rights on other computers. Return in descending order of the number of computers the computer account has local ](#31-find-every-instance-of-a-computer-account-having-local-admin-rights-on-other-computers-return-in-descending-order-of-the-number-of-computers-the-computer-account-has-local-admin-rights-on)  \n32. [Find users who are not marked as \"Sensitive and Cannot Be Delegated\" that have Administrative access to a computer, and where those users have sessions on servers with unconstrained delegation](#32-find-users-who-are-not-marked-as-sensitive-and-cannot-be-delegated-that-have-administrative-access-to-a-computer-and-where-those-users-have-sessions-on-servers-with-unconstrained-delegation-enabled)  \n33. [Gather the computers where the user is AdminTo and the computers with unconstrained delegation in lists (for better presentation and structure)](#33-gather-the-computers-where-the-user-is-adminto-and-the-computers-with-unconstrained-delegation-in-lists-for-better-presentation-and-structure)  \n34. [DOMAIN USERS is Admin of Computer](#34-domain-users-is-admin-of-computer)  \n35. [Find Shortest Path from DOMAIN USERS to High Value Targets](#35-find-shortest-path-from-domain-users-to-high-value-targets)  \n36. [Find ALL Path from DOMAIN USERS to High Value Targets](#36-find-all-path-from-domain-users-to-high-value-targets)  \n37. [Find all other right Domain Users shouldn’t have](#37-find-all-other-right-domain-users-shouldnt-have)  \n38. [Kerberoastable Accounts](#38-kerberoastable-accounts)  \n39. [Kerberoastable Accounts member of High Value Group](#39-kerberoastable-accounts-member-of-high-value-group)  \n40. [Find WORKSTATIONS where Domain Users can RDP To](#40-find-workstations-where-domain-users-can-rdp-to)  \n41. [Find SERVERS where Domain Users can RDP To](#41-find-servers-where-domain-users-can-rdp-to)  \n42. [Top 10 Computers with Most Admins](#42-top-10-computers-with-most-admins)  \n43. [How many High Value Target a Node can reach](#43-how-many-high-value-target-a-node-can-reach)  \n44. [All DA Account Sessions](#44-all-da-account-sessions)  \n45. [DA Sessions to NON DC](#45-da-sessions-to-non-dc)  \n46. [Count on how many non DC machines DA have sessions](#46-count-on-how-many-non-dc-machines-da-have-sessions)  \n47. [EXCLUDE PATH (Edge) on the fly](#47-exclude-path-edge-on-the-fly)  \n48. [Set SPN to a User](#48-set-spn-to-a-user)  \n49. [Add DOMAIN USERS as Admin to COMPxxxx](#49-add-domain-users-as-admin-to-compxxxx)  \n50. [Test our New Relationship](#50-test-our-new-relationship)  \n51. [Delete a Relationship](#51-delete-a-relationship)  \n52. [Shortest Path from Domain Users to Domain Admins](#52-shortest-path-from-domain-users-to-domain-admins)  \n53. [Shortest Path from Domain Users to Domain Admins (No AdminTo)](#53-shortest-path-from-domain-users-to-domain-admins-no-adminto)  \n54. [Find Admin Group not tagged highvalue](#54-find-admin-group-not-tagged-highvalue)  \n55. [Set Admin Group as highvalue](#55-set-admin-group-as-highvalue)  \n56. [Remore Admin User highvalue](#56-remore-admin-user-highvalue)  \n57. [If you want to enumerate all available properties](#57-if-you-want-to-enumerate-all-available-properties)  \n58. [List all computers with unconstraineddelegation](#58-list-all-computers-with-unconstraineddelegation)  \n59. [Computer where the most users can RDP to ](#59-computer-where-the-most-users-can-rdp-to)  \n60. [Average Length of Path](#60-average-length-of-path)  \n61. [Count how many Users have a path to DA](#61-count-how-many-users-have-a-path-to-da)  \n62. [Percent of Users that have a path to DA](#62-percent-of-users-that-have-a-path-to-da)  \n63. [Return users with shortest paths to high value targets by name](#63-return-users-with-shortest-paths-to-high-value-targets-by-name)  \n64. [Return labels i.e. group/name for a given SID](#64-return-labels-ie-groupusername-for-a-given-sid)\n65. [Return top 10 users with most Derivative local admin rights](#65-return-top-10-users-with-most-derivative-local-admin-rights)\n66. [Find all users WITHOUT a path to DA](#66-find-all-users-without-a-path-to-da)\n67. [Find users that have never logged on AND their account is still active](#67-find-users-that-have-never-logged-on-and-their-account-is-still-active)\n68. [Find users with DCSync rights who are not members of DA](#68-find-users-with-dcsync-rights-who-are-not-members-of-da) \n69. [Show attack paths from X domain to Specific Domain](#69-show-attack-paths-from-x-domain-to-specific-domain)  \n70. [Find all computers that are NOT dc's](#70-find-all-computers-that-are-NOT-dcs)\n  \n-----------------------------------------------------------------------\n\n\n### 1. Get a count of computers that do not have admins\n```\nMATCH (n)-[r:AdminTo]->(c:Computer)\nWITH COLLECT(c.name) as compsWithAdmins\nMATCH (c2:Computer) WHERE NOT c2.name in compsWithAdmins\nRETURN COUNT(c2)\n```\n\n### 2. Get the names of computers without admins, sorted in alphabetical order\n```\nMATCH (n)-[r:AdminTo]->(c:Computer)\nWITH COLLECT(c.name) as compsWithAdmins\nMATCH (c2:Computer) WHERE NOT c2.name in compsWithAdmins\nRETURN c2.name\nORDER BY c2.name ASC\n```\n\n### 3. Return a list of users who have admin rights on at least one system either explicitly or through group membership\n```\nMATCH (u:User)-[r:AdminTo|MemberOf*1..]->(c:Computer\nRETURN u.name\n```\n\n### 4. Return username and number of computers that username is admin for, for top N users\n```\nMATCH (U:User)-[r:MemberOf|:AdminTo*1..]->(C:Computer)\nWITH U.name as n, COUNT(DISTINCT(C)) as c \nRETURN n,c\nORDER BY c DESC LIMIT 5\n```\n\n### 5. Show all users that are administrator on more than one machine\n```\nMATCH (U:User)-[r:MemberOf|:AdminTo*1..]->(C:Computer)\nWITH U.name as n, COUNT(DISTINCT(C)) as c \nWHERE c>1\nRETURN n\nORDER BY c DESC\n```\n\n### 6. Show all users that are administrative on at least one machine, ranked by the number of machines they are admin on.\n```\nMATCH (u:User)\nOPTIONAL MATCH (u)-[:AdminTo]->(c1:Computer)\nOPTIONAL MATCH (u)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c2:Computer)\nWITH u, COLLECT(c1) + COLLECT(c2) AS tempVar\nUNWIND tempVar AS computers\nRETURN u.name AS UserName,COUNT(DISTINCT(computers)) AS AdminRightCount\nORDER BY AdminRightCount DESC\n```\n\n### 7. This will return cross domain 'HasSession' relationships\n```\nMATCH p=((S:Computer)-[r:HasSession*1]->(T:User)) \nWHERE NOT S.domain = T.domain\nRETURN p\n```\n\n### 8. Find all other Rights Domain Users shouldn't have\n```\nMATCH p=(m:Group)->[r:Owns|:WriteDacl|:GenericAll|:WriteOwner|:ExecuteDCOM|:GenericWrite|:AllowedToDelegate|:ForceChangePassword]->(n:Computer) \nWHERE m.name STARTS WITH ‘DOMAIN USERS’ \nRETURN p\n```\n\n### 9. Show Kerberoastable high value targets\n```\nMATCH (n:User)-[r:MemberOf]->(g:Group) WHERE g.highvalue=true AND n.hasspn=true RETURN n, g, r\n```\n\n\n### 10. Show computers where Domain Admins are logged in\n```\nMATCH (n:User)-[:MemberOf]->(g:Group {name:\"DOMAIN ADMINS@EXAMPLE.COM\"})\nWITH n as DAaccount\nMATCH (c:Computer)-[b:MemberOf]->(t:Group) WHERE NOT t.name = \"DOMAIN CONTROLLERS@EXAMPLE.COM\"\nWITH c as NonDC\nMATCH p = (NonDC)-[:HasSession]->(DAaccount)\n```\n\n\n### 11. Show groups with most localAdmin\n```\nMATCH (g:Group)\nWITH g\nOPTIONAL MATCH (g)-[r:AdminTo]->(c:Computer)\nWITH g,COUNT(c) as expAdmin\nOPTIONAL MATCH (g)-[r:MemberOf*1..]->(a:Group)-[r2:AdminTo]->(c:Computer)\nWITH g,expAdmin,COUNT(DISTINCT(c)) as unrolledAdmin\nRETURN g.name,expAdmin,unrolledAdmin, expAdmin + unrolledAdmin as totalAdmin\nORDER BY totalAdmin DESC \n```\nor\n```\nMATCH (g:Group)\nOPTIONAL MATCH (g)-[:AdminTo]->(c1:Computer)\nOPTIONAL MATCH (g)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c2:Computer)\nWITH g,COLLECT(c1) + COLLECT(c2) AS tempVar\nUNWIND tempVar AS comps\nRETURN g.name,COUNT(DISTINCT(comps)) AS compcount\nORDER BY compcount DESC\n```\nor\n```\nMATCH (g:Group)\nMATCH (g)-[:AdminTo]->(c:Computer)\nRETURN g.name,COUNT(c)\nORDER BY COUNT(c) DESC\n```\nor\n```\nMATCH (g:group)-[:AdminTo]->(c:Computer)\nRETURN g.name,COUNT(c)\nORDER BY COUNT(c) DESC\n```\nor\n```\nMATCH (g:Group)\nMATCH (g)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c:Computer)\nRETURN g.name,COUNT(c)\nORDER BY COUNT(c) DESC\n```\n\n### 12. List of unique users with a path (no \"GetChanges\" path) to a Group tagged as \"highvalue\"\n```\nMATCH (u:User)\nMATCH (g:Group {highvalue: True})\nMATCH p = shortestPath((u:User)-[r:AddMember|AdminTo|AllExtendedRights|AllowedToDelegate|CanRDP|Contains|ExecuteDCOM|ForceChangePassword|GenericAll|GenericWrite|GetChangesAll|GpLink|HasSession|MemberOf|Owns|ReadLAPSPassword|TrustedBy|WriteDacl|WriteOwner*1..]->(g))\nRETURN DISTINCT(u.name),u.enabled\norder by u.name\n```\n\n\n### 13. Return all users which can rdp to any system, if they belong to adm or svr accounts\n```\nMATCH (c:Computer) where c.name contains 'xxxxxx'\nMATCH (n:User)-[r:MemberOf]->(g:Group)  WHERE g.name = 'DOMAIN ADMINS@EXAMPLE.COM'\noptional match (g:Group)-[:CanRDP]->(c)\nOPTIONAL MATCH (u1:User)-[:CanRDP]->(c) where u1.enabled = true and u1.name contains 'ADM' OR u1.name contains 'SVR'\nOPTIONAL MATCH (u2:User)-[:MemberOf*1..]->(:Group)-[:CanRDP]->(c) where u2.enabled = true and u2.name contains 'ADM' OR u2.name contains 'SVR'\nWITH COLLECT(u1) + COLLECT(u2) + collect(n) as tempVar,c\nUNWIND tempVar as users\nRETURN c.name,COLLECT(users.name) as usernames\nORDER BY usernames  desc \n```\n\n### 14. Show the number of _users_ that have admin rights on each computer, in descending order\n```\nMATCH (c:Computer)\nOPTIONAL MATCH (u1:User)-[:AdminTo]->(c)\nOPTIONAL MATCH (u2:User)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c)\nWITH COLLECT(u1) + COLLECT(u2) AS tempVar,c\nUNWIND tempVar AS admins\nRETURN c.name AS computerName,COUNT(DISTINCT(admins)) AS adminCount\nORDER BY adminCount DESC\n```\n\n### 15. Stats percentage of enabled users that have a path to a high value group\n```\nMATCH (u:User {domain:'EXAMPLE.COM',enabled:True})\nMATCH (g:Group {domain:'EXAMPLE.COM'})\nWHERE g.highvalue = True\nWITH g, COUNT(u) as userCount\nMATCH p = shortestPath((u:User {domain:'EXAMPLE.COM',enabled:True})-[*1..]->(g))\nRETURN toint(100.0 * COUNT(distinct u) / userCount)\n```\n\n### 16. Shows machines that allow delegation that arent DCs\n```\nOPTIONAL MATCH (c:Computer)-[:MemberOf]->(t:Group)  \nWHERE NOT t.name =~ \"(?i)DOMAIN CONTROLLERS*.\"  \nWITH c as NonDC  \nMATCH (NonDC {unconstraineddelegation:true}) RETURN NonDC.name\n```  \n\n### 17. Groups with most local admin\n```\nMATCH (g:Group)\nWITH g\nOPTIONAL MATCH (g)-[r:AdminTo]->(c:Computer)\nWITH g,COUNT(c) as expAdmin\nRETURN g.name,expAdmin,expAdmin as totalAdmin\nORDER BY totalAdmin DESC\n```\n\n\n### 18. Find principles with DCSync rights\n```\nMATCH p=(n1)-[:MemberOf|GetChanges*1..]->(u:Domain {name: {result}}) WITH p,n1 \nMATCH p2=(n1)-[:MemberOf|GetChangesAll*1..]->(u:Domain {name: {result}}) WITH p,p2 \nMATCH p3=(n2)-[:MemberOf|GenericAll|AllExtendedRights*1..]->(u:Domain {name: {result}}) \nRETURN p,p2,p3\n```\n\n\n### 19. Find all Windows 7 computers\n```\nMATCH (c:Computer)\nWHERE toUpper(c.operatingsystem) CONTAINS \"Windows 7\"\nRETURN c\n```\n\n\n### 20. Find every user object where the \"userpassword\" attribute is populated. Neo4j web console only.\n```\nMATCH (u:User)\nWHERE NOT u.userpassword IS null\nRETURN u.name,u.userpassword\n```\n\n\n### 21. Find every user that doesn't require kerberos pre-authentication. Neo4j web console only.\n```\nMATCH (u:User {dontreqpreauth: true})\nRETURN u.name\n```\n\n\n### 22. Return any group where the name of the group contains the string \"SQL\" followed by the string \"ADMIN\". This will match \"SQL ADMINS\" and will also match \"SQL 2017 ADMINS\". Neo4j web console only.\n```\nMATCH (g:Group)\nWHERE g.name =~ '(?i).*SQL.*ADMIN.*'\nRETURN g.name\n```\n\n\n### 23. Find every OU that contains the string \"CITRIX\".\n```\nMATCH (o:OU)\nWHERE o.name =~ \"(?i).*CITRIX.*\"\nRETURN o\n```\n\n\n### 24. Find all computers with sessions from users of a different domain (Looking for cross-domain compromise opportunities). Neo4j web console only.\n```\nMATCH (c:Computer)-[:HasSession]->(u:User {domain:'FOO.BAR.COM'})\nWHERE NOT c.domain = u.domain\nRETURN u.name,COUNT(c)\n```\n\n\n### 25. Find all users trusted to perform constrained delegation, return in order of the number of target computers. Neo4j web console only.\n```\nMATCH (u:User)-[:AllowedToDelegate]->(c:Computer)\nRETURN u.name,COUNT(c)\nORDER BY COUNT(c) DESC\n```\n\n\n### 26. Return each OU in the database in order of the number of computers in that OU. Neo4j web console only.\n```\nMATCH (o:OU)-[:Contains]->(c:Computer)\nRETURN o.name,o.guid,COUNT(c)\nORDER BY COUNT(c) DESC\n```\n\n\n### 27. Return the name of every computer in the database where at least one SPN for the computer contains the string \"MSSQL\". Neo4j web console only.\n```\nMATCH (c:Computer)\nWHERE ANY (x IN c.serviceprincipalnames WHERE toUpper(x) CONTAINS \"MSSQL\")\nRETURN c.name,c.serviceprincipalnames\nORDER BY c.name ASC\n```\n\n\n### 28. Find groups with both users and computers that belong to the group. Neo4j web console only.\n```\nMATCH (c:Computer)-[r:MemberOf*1..]->(groupsWithComps:Group)\nWITH groupsWithComps\nMATCH (u:User)-[r:MemberOf*1..]->(groupsWithComps)\nRETURN DISTINCT(groupsWithComps) as groupsWithCompsAndUsers\n```\n\n\n### 29. Return each OU in the database that contains a Windows Server computer. Return rows where the columns are the name of the OU, the name of the computer, and the operating system of the computer. Neo4j web console only.\n```\nMATCH (o:OU)-[:Contains]->(c:Computer)\nWHERE toUpper(o.name) STARTS WITH \"WINDOWS SERVER\"\nRETURN o.name,c.name,c.operatingsystem\n```\n\n\n### 30. Find any computer that is NOT a domain controller that is trusted to perform unconstrained delegation. Neo4j web console only.\n```\nMATCH (c1:Computer)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectsid ENDS WITH \"-516\"\nWITH COLLECT(c1.name) AS domainControllers\nMATCH (c2:Computer {unconstraineddelegation:true})\nWHERE NOT c2.name IN domainControllers\nRETURN c2.name,c2.operatingsystem\nORDER BY c2.name ASC\n```\n\n\n### 31. Find every instance of a computer account having local admin rights on other computers. Return in descending order of the number of computers the computer account has local admin rights on.\n```\nMATCH (c1:Computer)\nOPTIONAL MATCH (c1)-[:AdminTo]->(c2:Computer)\nOPTIONAL MATCH (c1)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c3:Computer)\nWITH COLLECT(c2) + COLLECT(c3) AS tempVar,c1\nUNWIND tempVar AS computers\nRETURN c1.name,COUNT(DISTINCT(computers))\nORDER BY COUNT(DISTINCT(computers)) DESC\n```\n\n\n### 32. Find users who are not marked as \"Sensitive and Cannot Be Delegated\" that have Administrative access to a computer, and where those users have sessions on servers with Unconstrained Delegation enabled  \n```\nMATCH (n {sensitive:FALSE})-[:MemberOf*0..5]->(g:Group)-[:AdminTo]->(c:Computer) \nWITH n,c MATCH (d:Computer {unconstraineddelegation:TRUE})-[:HasSession]->(n:User) \nRETURN n.name AS user,\nc.name as AdminTo ,\nd.name as TicketLocation\n```\n----or this one does sort of the same thing?----- \n```\nMATCH (u:User {sensitive:false})-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c1:Computer)\nWITH u,c1\nMATCH (c2:Computer {unconstraineddelegation:true})-[:HasSession]->(u)\nRETURN u.name AS user,c1.name AS AdminTo,c2.name AS TicketLocation\nORDER BY user ASC\n```\n\n### 33. Gather the computers where the user is AdminTo and the computers with unconstrained delegation in lists (for better presentation and structure)\n```\nMATCH (u:User {sensitive:false})-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c1:Computer)\nWITH u,c1\nMATCH (c2:Computer {unconstraineddelegation:true})-[:HasSession]->(u)\nRETURN u.name AS user,COLLECT(DISTINCT(c1.name)) AS AdminTo,COLLECT(DISTINCT(c2.name)) AS TicketLocation\nORDER BY user ASC\n```\n\n### 34. DOMAIN USERS is Admin of Computer \n```\nMATCH p=(m:Group)-[r:AdminTo]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p\n```\n\n### 35. Find Shortest Path from DOMAIN USERS to High Value Targets\n```\nMATCH (g:Group),(n {highvalue:true}),p=shortestPath((g)-[*1..]->(n)) \nWHERE g.name STARTS WITH 'DOMAIN USERS' \nRETURN p\n```\n\n### 36. Find ALL Path from DOMAIN USERS to High Value Targets\n```\nMATCH (g:Group) WHERE g.name STARTS WITH 'DOMAIN USERS'  MATCH (n {highvalue:true}),p=shortestPath((g)-[r*1..]->(n)) return p\n```\n\n### 37. Find all other right Domain Users shouldn’t have\n```\nMATCH p=(m:Group)-[r:Owns|:WriteDacl|:GenericAll|:WriteOwner|:ExecuteDCOM|:GenericWrite|:AllowedToDelegate|:ForceChangePassword]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p\n```\n\n### 38. Kerberoastable Accounts\n```\nMATCH (n:User)WHERE n.hasspn=true RETURN n\n```\n\n### 39. Kerberoastable Accounts member of High Value Group\n```\nMATCH (n:User)-[r:MemberOf]->(g:Group) WHERE g.highvalue=true AND n.hasspn=true RETURN n, g, r\n```\n\n### 40. Find WORKSTATIONS where Domain Users can RDP To\n```\nmatch p=(g:Group)-[:CanRDP]->(c:Computer) \nwhere g.name STARTS WITH 'DOMAIN USERS' AND NOT c.operatingsystem CONTAINS 'Server' \nreturn p\n```\n\n### 41. Find SERVERS where Domain Users can RDP To\n```\nmatch p=(g:Group)-[:CanRDP]->(c:Computer) \nwhere g.name STARTS WITH 'DOMAIN USERS' \nAND c.operatingsystem CONTAINS 'Server' \nreturn p\n```\n\n### 42. Top 10 Computers with Most Admins\n```\nMATCH (n:User),(m:Computer), (n)-[r:AdminTo]->(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH m, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)<-[r:AdminTo]-(n) RETURN p\n```\n\n\n### 43. How many High Value Target a Node can reach\n```\nMATCH p = shortestPath((n)-[*1..]->(m {highvalue:true}))\nWHERE NOT n = m\nRETURN DISTINCT(m.name),LABELS(m)[0],COUNT(DISTINCT(n))\nORDER BY COUNT(DISTINCT(n)) DESC\n```\n \n### 44. All DA Account Sessions\n```\nMATCH (n:User)-[:MemberOf]->(g:Group {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"}) \nMATCH p = (c:Computer)-[:HasSession]->(n) \nreturn p\n```\n\n### 45. DA Sessions to NON DC\n```\nOPTIONAL MATCH (c:Computer)-[:MemberOf]->(t:Group) \nWHERE NOT t.name = \"DOMAIN CONTROLLERS@TESTLAB.LOCAL\"\nWITH c as NonDC\nMATCH p=(NonDC)-[:HasSession]->(n:User)-[:MemberOf]->\n(g:Group {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"})\nRETURN DISTINCT (n.name) as Username, COUNT(DISTINCT(NonDC)) as Connexions\nORDER BY COUNT(DISTINCT(NonDC)) DESC\n```\n\n### 46. Count on how many non DC machines DA have sessions\n```\nMATCH (c:Computer)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectsid ENDS WITH \"-516\"\nWITH c.name as DomainControllers\nMATCH p = (c2:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectsid ENDS WITH \"-512\" AND NOT c2.name in DomainControllers\nRETURN DISTINCT(u.name),COUNT(DISTINCT(c2))\nORDER BY COUNT(DISTINCT(c2)) DESC\n```\n\n### 47. EXCLUDE PATH (Edge) on the fly\n```\nMATCH (n:User),(m:Group {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"}),\np=shortestPath((n)-[r*1..]->(m)) \nWHERE ALL(x in relationships(p) WHERE type(x) <> \"AdminTo\") \nRETURN p\n```\n\n\n### 48. Set SPN to a User\n```\nMATCH (n:User {name:\"JNOA00093@TESTLAB.LOCAL\"}) SET n.hasspn=true\n```\n\n\n### 49. Add DOMAIN USERS as Admin to COMPxxxx\n```\nMERGE (n:Group {name:\"DOMAIN USERS@TESTLAB.LOCAL\"}) WITH n MERGE (m:Computer {name:\"COMP00673.TESTLAB.LOCAL\"}) WITH n,m MERGE (n)-[:AdminTo]->(m)\n```\n\n### 50. Test our New Relationship \n```\nMATCH p=(n:Group {name:\"DOMAIN USERS@TESTLAB.LOCAL\"})-[r:AdminTo]->(m:Computer {name:\"COMP00673.TESTLAB.LOCAL\"}) \nRETURN p\n```\n#### Might try to replace AdminTo by 1**\n\n### 51. Delete a Relationship\n```\nMATCH p=(n:Group {name:\"DOMAIN USERS@TESTLAB.LOCAL\"})-[r:AdminTo]->\n(m:Computer {name:\"COMP00673.TESTLAB.LOCAL\"}) \nDELETE r\n```\n\n\n### 52. Shortest Path from Domain Users to Domain Admins\n```\nMATCH (g:Group {name:\"DOMAIN USERS@TESTLAB.LOCAL\"}),\n(n {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"}),\np=shortestPath((g)-[r*1..]->(n)) \nreturn p\n```\n\n\n### 53. Shortest Path from Domain Users to Domain Admins (No AdminTo)\n```\nMATCH (g:Group {name:\"DOMAIN USERS@TESTLAB.LOCAL\"}),\n(n {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"}),\np=shortestPath((g)-[r*1..]->(n)) \nWHERE ALL(x in relationships(p) WHERE type(x) <> \"AdminTo\") \nreturn p\n```\n\n\n### 54. Find Admin Group not tagged highvalue\n```\nMATCH (g:Group)\nWHERE g.name CONTAINS \"ADMIN\"\nAND g.highvalue IS null\nRETURN g.name\n```\n\n### 55. Set Admin Group as highvalue\n```\nMATCH (g:Group)\nWHERE g.name CONTAINS \"ADMIN\"\nAND g.highvalue IS null\nSET g.highvalue=true\n```\n\n### 56. Remore Admin User highvalue\n```\nMATCH p=(g:Group {highvalue: true})<-[:MemberOf]-(u:User)\nWHERE g.name CONTAINS \"ADMIN\"\nSET g.highvalue = NULL\n```\n\n### 57. If you want to enumerate all available properties\n``` \nMatch (n:Computer) return properties(n)\n```\n\n### 58. List all computers with unconstraineddelegation\n```\nMATCH (c:Computer {unconstraineddelegation:true})\nreturn c.name\n```\n\n### 59. Computer where the most users can RDP to \n```\nMATCH (c:Computer)\nOPTIONAL MATCH (u1:User)-[:CanRDP]->(c)\nOPTIONAL MATCH (u2:User)-[:MemberOf*1..]->(:Group)-[:CanRDP]->(c)\nWITH COLLECT(u1) + COLLECT(u2) as tempVar,c\nUNWIND tempVar as users\nRETURN c.name,COUNT(DISTINCT(users))\nORDER BY COUNT(DISTINCT(users)) DESC\n```\n\n### 60. Average Length of Path\n```\nMATCH (g:Group {name:'DOMAIN ADMINS@CONTOSO.LOCAL'})\nMATCH p = shortestPath((u:User)-[r:AdminTo|MemberOf|HasSession*1..]->(g))\nWITH EXTRACT(n in NODES(p) | LABELS(n)[0]) as pathNodes\nWITH FILTER(x IN pathNodes WHERE x = \"Computer\") as filteredPathNodes\nRETURN AVG(LENGTH(filteredPathNodes))\n```\n\n### 61. Count how many Users have a path to DA\n```\nMATCH p=shortestPath((u:User)-[*1..]->\n(m:Group {name: \"DOMAIN ADMINS@TESTLAB.LOCAL\"}))\nRETURN COUNT (DISTINCT(u))\n```\n\n### 62. Percent of Users that have a path to DA\n```\nOPTIONAL MATCH p=shortestPath((u:User)-[*1..]->\n(m:Group {name: \"DOMAIN ADMINS@TESTLAB.LOCAL\"}))\nOPTIONAL MATCH (uT:User)\nWITH COUNT (DISTINCT(uT)) as uTotal, COUNT (DISTINCT(u)) as uHasPath\nRETURN uHasPath / uTotal * 100 as Percent\n```\n\n### 63. Return users with shortest paths to high value targets by name\n```\nMATCH (u:User)\nMATCH (g:Group {highvalue: True})\nMATCH p = shortestPath((u:User)-[r:AddMember|AdminTo|AllExtendedRights|AllowedToDelegate|CanRDP|Contains|ExecuteDCOM|ForceChangePassword|GenericAll|GenericWrite|GetChangesAll|GpLink|HasSession|MemberOf|Owns|ReadLAPSPassword|TrustedBy|WriteDacl|WriteOwner*1..]->(g))\nRETURN DISTINCT(u.name),u.enabled\norder by u.name\n```\n\n### 64. Return labels i.e. group,username for a given SID\n```\nMATCH (n {objectsid:\"S-1-5-21-971234526-3761234589-3049876599-500\"}) RETURN labels(n)\n```\n\n### 65. Return top 10 users with most Derivative local admin rights\n```\nMATCH (u:User)\nOPTIONAL MATCH (u)-[:AdminTo]->(c1:Computer)\nOPTIONAL MATCH (u)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c2:Computer)\nWITH COLLECT(c1) + COLLECT(c2) as tempVar,u\nUNWIND tempVar AS computers\nRETURN u.name,COUNT(DISTINCT(computers)) AS is_admin_on_this_many_boxes\nORDER BY is_admin_on_this_many_boxes DESC\n```\n\n\n### 66. Find all users WITHOUT a path to da  \n```\nMATCH (n:User),(m:Group {name:\"DOMAIN ADMINS@CONTOSO.LOCAL\"}) WHERE NOT EXISTS ((n)-[*]->(m)) RETURN n.name  \n```\n  \n  \n### 67. Find users that have never logged on AND their account is still active  \n```\nMATCH (n:User) WHERE n.lastlogontimestamp=-1.0 AND n.enabled=TRUE RETURN n.name ORDER BY n.name  \n```\n  \n### 68. Find users with DCSync rights who are not members of DA\n```\nMATCH (n1)-[:MemberOf|GetChanges*1..]->(u:Domain {name: \"TESTLAB.LOCAL\"}) WITH n1,u \nMATCH (n1)-[:MemberOf|GetChangesAll*1..]->(u) WITH n1,u \nMATCH p = (n1)-[:MemberOf|GetChanges|GetChangesAll*1..]->(u) WHERE NOT (n1)-[:MemberOf*1..]->(:Group {name:\"DOMAIN ADMINS@TESTLAB.LOCAL\"}) \nRETURN p\n```\n\n### 69. Show attack paths from X domain to Specific Domain\n```\nMATCH p=(n)-[r]->(m) WHERE NOT n.domain = m.domain RETURN p  \n```\nor specific domains  \n```\nMATCH p=(n {domain:\"lab.local\")-[r]->(m {domain:\"test.local\"}) RETURN p\n```\n\n### 70. Find all computers that are NOT dc's\n```\nMATCH (dc:Computer)-[:MemberOf*1..]->(g:Group)\nWHERE g.name STARTS WITH('DOMAIN CONTROLLERS')\nWITH COLLECT(dc) as dcs\nMATCH (c:Computer) WHERE NOT c in dcs\nRETURN COUNT(c)\n```\nor using objectID  \n```\nMATCH (c1:Computer)-[:MemberOf*1..]->(g:Group)\nWHERE g.objectid ENDS WITH \"-516\"\nWITH COLLECT(c1) as dcs\nMATCH (c:Computer) WHERE NOT c in dcs\nRETURN COUNT(c)\n```\n\n  \n## References\nReading materials / References::  \nhttps://github.com/BloodHoundAD/BloodHound/wiki  \nhttps://github.com/Scoubi/BloodhoundAD-Queries  \nhttps://github.com/porterhau5/BloodHound-Owned  \nhttps://porterhau5.com/blog/extending-bloodhound-track-and-visualize-your-compromise/  \nhttps://blog.cptjesus.com/posts/introtocypher#building-on-top   \n  \n"
  },
  {
    "path": "customqueries.json",
    "content": "{\n    \"queries\": \n    [\n        {\n            \"name\": \"Shortest Paths to High Value Targets from Owned Principles\",\n            \"queryList\": [\n                {\n                    \"final\": false,\n                    \"title\": \"Select a Domain\",\n                    \"query\": \"MATCH (n:Domain) RETURN n.name ORDER BY n.name DESC\"\n                },\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n),(m),p=shortestPath((n)-[r:{}*1..]->(m)) WHERE m.domain={result} AND m.highvalue=true AND NOT m = n AND n.owned=true RETURN p\",\n                    \"allowCollapse\": true,\n                    \"endNode\": \"{}\"\n                }\n            ]\n        },\n        {\n           \"name\": \"List Computers where DOMAIN USERS are Local Admin\",\n           \"queryList\": [\n               {\n                   \"final\": true,\n                   \"query\":\n                       \"MATCH p=(m:Group)-[r:AdminTo]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p\",\n                   \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n           \"name\": \"Find Workstations where DOMAIN USERS can RDP To\",\n           \"queryList\": [\n               {\n                   \"final\": true,\n                   \"query\":\n                       \"match p=(g:Group)-[:CanRDP]->(c:Computer) where g.name STARTS WITH 'DOMAIN USERS' AND NOT c.operatingsystem CONTAINS 'Server' return p\",\n                   \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n           \"name\": \"Find Servers where DOMAIN USERS can RDP To\",\n           \"queryList\": [\n               {\n                   \"final\": true,\n                   \"query\":\n                       \"match p=(g:Group)-[:CanRDP]->(c:Computer) where g.name STARTS WITH 'DOMAIN USERS' AND c.operatingsystem CONTAINS 'Server' return p\",\n                   \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"ALL Path from DOMAIN USERS to High Value Targets\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (g:Group) WHERE g.name STARTS WITH 'DOMAIN USERS'  MATCH (n {highvalue:true}),p=shortestPath((g)-[r*1..]->(n)) return p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Find all other Rights DOMAIN USERS shouldn’t have\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH p=(m:Group)-[r:Owns|:WriteDacl|:GenericAll|:WriteOwner|:ExecuteDCOM|:GenericWrite|:AllowedToDelegate|:ForceChangePassword]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"DA Account Sessions\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User)-[:MemberOf]->(g:Group) WHERE g.name STARTS WITH 'DOMAIN ADMINS' MATCH p = (c:Computer)-[:HasSession]->(n) return p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"DA Account Sessions to NON DC\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (c:Computer)-[:MemberOf]->(t:Group) WHERE NOT t.name STARTS WITH 'DOMAIN CONTROLLERS' WITH c as NonDC MATCH p=(NonDC)-[:HasSession]->(n:User)-[:MemberOf]-> (g:Group WHERE g.name STARTS WITH 'DOMAIN ADMINS') RETURN p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Kerberoastable Accounts member of High Value Group\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User)-[r:MemberOf]->(g:Group) WHERE g.highvalue=true AND n.hasspn=true RETURN n, g, r\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"List all Kerberoastable Accounts\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User)WHERE n.hasspn=true RETURN n\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Top Ten Users with Most Sessions\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User),(m:Computer), (n)<-[r:HasSession]-(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH n, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)-[r:HasSession]->(n) RETURN p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Top Ten Computers with Most Admins\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User),(m:Computer), (n)-[r:AdminTo]->(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH m, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)<-[r:AdminTo]-(n) RETURN p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },        \n        {\n            \"name\": \"Top Ten Computers with Most Sessions\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User),(m:Computer), (n)<-[r:HasSession]-(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH m, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)-[r:HasSession]->(n) RETURN n,r,m\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Top Ten Computers with Most Admin Sessions\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User),(m:Computer), (n)<-[r:HasSession]-(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH m, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)-[r:HasSession]->(n) RETURN n,r,m\",\n                    \"allowCollapse\": true\n                }\n            ]\n        },\n        {\n            \"name\": \"Top Ten Users with Most Local Admin Rights\",\n            \"queryList\": [\n                {\n                    \"final\": true,\n                    \"query\":\n                        \"MATCH (n:User),(m:Computer), (n)-[r:AdminTo]->(m) WHERE NOT n.name STARTS WITH 'ANONYMOUS LOGON' AND NOT n.name='' WITH n, count(r) as rel_count order by rel_count desc LIMIT 10 MATCH p=(m)<-[r:AdminTo]-(n) RETURN p\",\n                    \"allowCollapse\": true\n                }\n            ]\n        }\n    ]\n}\n"
  }
]