From 29e7f890a5eea3d7b070dcd1b938a79be45b651c Mon Sep 17 00:00:00 2001 From: "Mariusz B. / mgeeky" Date: Wed, 6 Apr 2022 11:12:32 +0200 Subject: [PATCH] Updated Handy BloodHound Cypher Queries. --- .../Handy-BloodHound-Cypher-Queries.md | 286 ++++++++++-------- 1 file changed, 154 insertions(+), 132 deletions(-) diff --git a/red-teaming/Handy-BloodHound-Cypher-Queries.md b/red-teaming/Handy-BloodHound-Cypher-Queries.md index 8434bb3..ee24884 100644 --- a/red-teaming/Handy-BloodHound-Cypher-Queries.md +++ b/red-teaming/Handy-BloodHound-Cypher-Queries.md @@ -1,27 +1,4 @@ -- Returns computer names and their operating system for statistics purposes -``` -MATCH (c:Computer) WHERE c.operatingsystem is not null RETURN c.name as Name, c.operatingsystem as OS -``` - -- Returns a summary report of machines grouped by their operating systems versions, along with number of machines running specific OS version: -``` -MATCH (c:Computer) WHERE c.operatingsystem is not null MATCH (n:Computer {operatingsystem: c.operatingsystem}) RETURN c.operatingsystem as OS, count(distinct n) AS Number ORDER BY Number DESC -``` - -- Returns non-DC computers that enable unconstrained delegation along with their LDAP DN paths and operating systems.: -``` -MATCH (c:Computer {unconstraineddelegation: True}), (g:Group) WHERE g.name starts with 'DOMAIN CONTROLLERS' MATCH (c) WHERE NOT (c)-[:MemberOf]->(g) RETURN c.name, c.distinguishedname, c.operatingsystem -``` - -- Returns a list of OUs along with their members count (source: [hausec.com](https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/) ) -``` -MATCH (o:OU)-[:Contains]->(c) RETURN o.name,o.guid, COUNT(c) ORDER BY COUNT(c) DESC -``` - -- Returns all objects that have SPNs set and checks whether they are allowed to delegate, have admincount set or can be used for unconstrained delegation: -``` -MATCH (c {hasspn: True}) RETURN c.name as name, c.allowedtodelegate as AllowedToDelegate, c.unconstraineddelegation as UnconstrainedDelegation, c.admincount as AdminCount, c.serviceprincipalnames as SPNs -``` +### General - Counts various Active Directory statistics and weaknesses. (Change `ENDS WITH ""` to `ENDS WITH "contoso.com"` to limit results to specified domain): ``` @@ -43,6 +20,47 @@ MATCH (u {owned: true}) WHERE toLower(u.name) ENDS WITH "" RETURN MATCH (u {highvalue: true}) WHERE toLower(u.name) ENDS WITH "" RETURN "High Value" AS what, count(u) AS number ``` +- Returns all objects that have SPNs set and checks whether they are allowed to delegate, have admincount set or can be used for unconstrained delegation: +``` +MATCH (c {hasspn: True}) RETURN c.name as name, c.allowedtodelegate as AllowedToDelegate, c.unconstraineddelegation as UnconstrainedDelegation, c.admincount as AdminCount, c.serviceprincipalnames as SPNs +``` + +- Returns Top 20 **Outbound Control Rights** --> **First Degree Object Control** principals in domain: +``` +MATCH p=(u)-[r1]->(n) WHERE r1.isacl=true +WITH u.name as name, LABELS(u)[1] as type, +COUNT(DISTINCT(n)) as controlled +WHERE name IS NOT NULL +RETURN type, name, controlled +ORDER BY controlled DESC +LIMIT 20 +``` + +- Returns Top 20 **Outbound Control Rights** --> **Group Delegated Object Control** principals in domain and whether that object is member of high privileged group (such a `Domain Admins` or `Domain Controllers`): +``` +MATCH p=(u)-[r1:MemberOf*1..]->(g:Group)-[r2]->(n) WHERE r2.isacl=true +WITH u.name as name, LABELS(u)[1] as type, g.highvalue as highly_privileged, +COUNT(DISTINCT(n)) as controlled +WHERE name IS NOT NULL +RETURN type, name, highly_privileged, controlled +ORDER BY controlled DESC +LIMIT 20 +``` + +- Returns Top 10 **Outbound Control Rights** --> **Transitive Object Control** in domain (TAKES ENORMOUS TIME TO COMPUTE! You were warned): +``` +MATCH p=shortestPath((u)-[r1:MemberOf|AddMember|AllExtendedRights|ForceChangePassword|GenericAll|GenericWrite|WriteDacl|WriteOwner|Owns*1..]->(n)) +WHERE u<>n +WITH u.name as name, LABELS(u)[1] as type, +COUNT(DISTINCT(n)) as controlled +WHERE name IS NOT NULL +RETURN type, name, controlled +ORDER BY controlled DESC +LIMIT 10 +``` + +### Users + - Pulls users eligible for ASREP roasting ``` MATCH (u:User {dontreqpreauth: true}) RETURN u.name, u.displayname, u.description, u.objectid @@ -88,9 +106,14 @@ MATCH p=shortestPath((u:User {hasspn: true})-[r:MemberOf*1..]->(g:Group {highval MATCH (A:User),(B:Group),p=shortestPath((A)-[*1..]->(B)) WHERE A.hasspn=true AND B.name STARTS WITH 'DOMAIN ADMINS' RETURN p ``` -- Pull GPOs linked to users being member of a specified group: +- Shortest path from any user that has PASSWORD_NOT_REQUIRED set to any computer ``` -MATCH p = (:GPO)-[:GpLink]->(d)-[:Contains*1..]->(u:User)-[:MemberOf*1..]->(g:Group {name:'GROUP_NAME@CONTOSO.LOCAL'}) RETURN p +MATCH (m:User {enabled: True, passwordnotreqd: True}), (n:Computer), p = shortestPath((m)-[*1..]->(n)) RETURN p +``` + +- Find all users that have userPassword attribute not empty +``` +MATCH (u:User) WHERE u.userpassword =~ ".+" RETURN u.name, u.userpassword, u.displayname, u.description, u.objectid ``` - Return enabled users that have PASSWORD_NOT_REQUIRED flag set in their UserAccountControl field (thus they have an empty password set) @@ -108,111 +131,16 @@ MATCH (u:User {enabled: True, dontreqpreauth: true}) RETURN u.name, u.displaynam MATCH (m:User {enabled: True, passwordnotreqd: True}), (n:Group), p = shortestPath((m)-[*1..]->(n)) WHERE n.name STARTS WITH 'DOMAIN ADMINS' RETURN p ``` -- Shortest path from any user that has PASSWORD_NOT_REQUIRED set to any computer -``` -MATCH (m:User {enabled: True, passwordnotreqd: True}), (n:Computer), p = shortestPath((m)-[*1..]->(n)) RETURN p -``` - -- Find all users that have userPassword attribute not empty -``` -MATCH (u:User) WHERE u.userpassword =~ ".+" RETURN u.name, u.userpassword, u.displayname, u.description, u.objectid -``` - -- Counts unrolled members of Tier-0 privileged AD groups (copy all query lines, as they are UNION ALL joined): -``` -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "ENTERPRISE ADMINS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DOMAIN ADMINS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "SCHEMA ADMIN" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "ACCOUNT OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "BACKUP OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "PRINT OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "SERVER OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DOMAIN CONTROLLERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "READ-ONLY DOMAIN CONTROLLERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "GROUP POLICY CREATOR OWNERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "CRYPTOGRAPHIC OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL -MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DISTRIBUTED COM USERS" RETURN g.name AS GroupName, count(u) AS MembersCounted -``` - -- Retrieves nodes having particular juicy keywords in their description properties: -``` -MATCH (n) WHERE n.description CONTAINS 'pass' RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'secret' RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'admin' RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'sensitive' RETURN n.name, n.description -``` - -- Show only owned nodes of the above ones: -``` -MATCH (n) WHERE n.description CONTAINS 'pass' and n.owned = TRUE RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'secret' and n.owned = TRUE RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'admin' and n.owned = TRUE RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS 'sensitive' and n.owned = TRUE RETURN n.name, n.description UNION -MATCH (n) WHERE n.description CONTAINS '\\' and n.owned = TRUE RETURN n.name, n.description -``` - -- Retrieves nodes that contain UNC paths to SMB shares in their description fields: -``` -MATCH (n) WHERE n.description CONTAINS '\\\\' RETURN n.name, n.description -``` - -- Returns shortest path from any of owned nodes to any of highvalue nodes: -``` -RETURN shortestPath((O:{owned:True})-[*1..]->(H {highvalue: True})) -``` - - Find all users that have direct or indirect admin privileges over a computer: ``` MATCH (u:User)-[r:AdminTo|MemberOf*1..]->(c:Computer) RETURN u.name ``` -- Print GPO names and their container paths: +- Find all the users that can RDP into a machine where they have special privileges: ``` -MATCH (n:GPO) return n.name,n.gpcpath -``` - -- Print GPOs with interesting words in their names along with their container paths: -``` -unwind ["360totalsecurity", "access", "acronis", "adaware", "admin", "admin", "aegislab", "ahnlab", "alienvault", "altavista", "amsi", "anti-virus", "antivirus", "antiy", "apexone", "applock", "arcabit", "arcsight", "atm", "atp", "av", "avast", "avg", "avira", "baidu", "baiduspider", "bank", "barracuda", "bingbot", "bitdefender", "bluvector", "canary", "carbon", "carbonblack", "certificate", "check", "checkpoint", "citrix", "clamav", "code42", "comodo", "countercept", "countertack", "credential", "crowdstrike", "custom", "cyberark", "cybereason", "cylance", "cynet360", "cyren", "darktrace", "datadog", "defender", "druva", "drweb", "duckduckbot", "edr", "egambit", "emsisoft", "encase", "endgame", "ensilo", "escan", "eset", "exabot", "exception", "f-secure", "f5", "falcon", "fidelis", "fireeye", "firewall", "fix", "forcepoint", "forti", "fortigate", "fortil", "fortinet", "gdata", "gravityzone", "guard", "honey", "huntress", "identity", "ikarussecurity", "insight", "ivanti", "juniper", "k7antivirus", "k7computing", "kaspersky", "kingsoft", "kiosk", "laps", "lightcyber", "logging", "logrhythm", "lynx", "malwarebytes", "manageengine", "mass", "mcafee", "microsoft", "mj12bot", "msnbot", "nanoav", "nessus", "netwitness", "office365", "onedrive", "orion", "palo", "paloalto", "paloaltonetworks", "panda", "pass", "powershell", "proofpoint", "proxy", "qradar", "rdp", "rsa", "runasppl", "sandboxe", "sap", "scanner", "scanning", "sccm", "script", "secret", "secureage", "secureworks", "security", "sensitive", "sentinel", "sentinelone", "slurp", "smartcard", "sogou", "solarwinds", "sonicwall", "sophos", "splunk", "superantispyware", "symantec", "tachyon", "temporary", "tencent", "totaldefense", "transfer", "trapmine", "trend micro", "trendmicro", "trusteer", "trustlook", "uac", "vdi", "virusblokada", "virustotal", "virustotalcloud", "vpn", "vuln", "webroot", "whitelist", "wifi", "winrm", "workaround", "yubikey", "zillya", "zonealarm", "zscaler"] as word match (n:GPO) where toLower(n.name) CONTAINS toLower(word) RETURN word, n.name, n.description, n.gpcpath ORDER BY n.name -``` - -- Print **Security Solutions** (think SIEM, EDRs, AVs, Anomaly detection systems, etc) deployed in the company by searching for keywords in _name, description, distinguishedname_ of all objects (User, Group, Computer, OU, ...) -``` -UNWIND ["360totalsecurity", "acronis", "adaware", "aegislab", "ahnlab", "alienvault", "altavista", "anti-virus", "antivirus", "antiy", "apexone", "arcabit", "arcsight", "attivo", "avast", "avg", "avira", "baidu", "baiduspider", "barracuda", "bingbot", "bitdefender", "bitdefender", "bluecoat", "bluvector", "canary", "carbon", "carbonblack", "carbonblack", "check", "checkpoint", "clamav", "code42", "comodo", "cortex", "countercept", "countertack", "crowdstrike", "cyberark", "cybereason", "cylance", "cynet360", "cyren", "darktrace", "datadog", "defender", "druva", "drweb", "duckduckbot", "edr", "egambit", "emsisoft", "encase", "endgame", "ensilo", "escan", "eset", "exabot", "f-secure", "f5", "falcon", "fidelis", "fireeye", "forcepoint", "fortigate", "fortil", "fortinet", "gdata", "gdata", "gravityzone", "honey", "huntress", "ia_archiver", "ikarussecurity", "ivanti", "juniper", "k7antivirus", "k7computing", "kaspersky", "kingsoft", "lightcyber", "lynx", "malwarebytes", "mcafee", "microsoft", "mj12bot", "morphisec", "msnbot", "nanoav", "nessus", "netwitness", "office365", "palo", "paloalto", "paloaltonetworks", "panda", "proofpoint", "qradar", "sandboxe", "scanner", "scanning", "secureage", "secureworks", "security", "sentinelone", "simplepie", "slurp", "sogou", "solarwinds", "sonicwall", "sophos", "splunk", "superantispyware", "symantec", "tachyon", "tencent", "totaldefense", "trapmine", "trend", "trendmicro", "trusteer", "trustlook", "virus", "virustotal", "virustotalcloud", "webroot", "zillya", "zonealarm", "zscaler"] AS word MATCH (n) WHERE toLower(n.name) CONTAINS toLower(word) OR toLower(n.description) CONTAINS toLower(word) OR toLower(n.distinguishedname) CONTAINS toLower(word) RETURN word as keyword, LABELS(n)[1] as type, n.name, n.description, n.distinguishedname ORDER BY n.name -``` - -- Returns Top 20 **Outbound Control Rights** --> **First Degree Object Control** principals in domain: -``` -MATCH p=(u)-[r1]->(n) WHERE r1.isacl=true -WITH u.name as name, LABELS(u)[1] as type, -COUNT(DISTINCT(n)) as controlled -WHERE name IS NOT NULL -RETURN type, name, controlled -ORDER BY controlled DESC -LIMIT 20 -``` - -- Returns Top 20 **Outbound Control Rights** --> **Group Delegated Object Control** principals in domain and whether that object is member of high privileged group (such a `Domain Admins` or `Domain Controllers`): -``` -MATCH p=(u)-[r1:MemberOf*1..]->(g:Group)-[r2]->(n) WHERE r2.isacl=true -WITH u.name as name, LABELS(u)[1] as type, g.highvalue as highly_privileged, -COUNT(DISTINCT(n)) as controlled -WHERE name IS NOT NULL -RETURN type, name, highly_privileged, controlled -ORDER BY controlled DESC -LIMIT 20 -``` - -- Returns Top 10 **Outbound Control Rights** --> **Transitive Object Control** in domain (TAKES ENORMOUS TIME TO COMPUTE! You were warned): -``` -MATCH p=shortestPath((u)-[r1:MemberOf|AddMember|AllExtendedRights|ForceChangePassword|GenericAll|GenericWrite|WriteDacl|WriteOwner|Owns*1..]->(n)) -WHERE u<>n -WITH u.name as name, LABELS(u)[1] as type, -COUNT(DISTINCT(n)) as controlled -WHERE name IS NOT NULL -RETURN type, name, controlled -ORDER BY controlled DESC -LIMIT 10 +MATCH (u:User)-[:CanRDP]->(c:Computer) WITH u,c +OPTIONAL MATCH (u)-[:MemberOf*1..]->(g:Group)-[:CanRDP]->(c) WITH u,c +MATCH (u)-[:CanPrivesc]->(c) RETURN u.name, c.name ``` - Pulls Kerberoastable users and returns their **Outbound Control Rights** --> **First Degree Object Control** in domain: @@ -297,6 +225,14 @@ RETURN u.name,expAdmin,unrolledAdmin,expAdmin + unrolledAdmin as totalAdmin ORDER BY totalAdmin ASC ``` +- Returns shortest path from any of owned nodes to any of highvalue nodes: +``` +RETURN shortestPath((O:{owned:True})-[*1..]->(H {highvalue: True})) +``` + + +### Groups + - Find the most privileged groups on the domain (author: [hausec](https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/) ): ``` MATCH (g:Group) OPTIONAL MATCH (g)-[:AdminTo]->(c1:Computer) OPTIONAL MATCH (g)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c2:Computer) WITH g, COLLECT(c1) + COLLECT(c2) AS tempVar UNWIND tempVar AS computers RETURN g.name AS GroupName,COUNT(DISTINCT(computers)) AS AdminRightCount ORDER BY AdminRightCount DESC @@ -307,9 +243,37 @@ MATCH (g:Group) OPTIONAL MATCH (g)-[:AdminTo]->(c1:Computer) OPTIONAL MATCH (g)- MATCH (g:Group) WITH g OPTIONAL MATCH (g)-[r:AdminTo]->(c1:Computer) WITH g,COUNT(c1) as explicitAdmins OPTIONAL MATCH (g)-[r:MemberOf*1..]->(a:Group)-[r2:AdminTo]->(c2:Computer) WITH g,explicitAdmins,COUNT(DISTINCT(c2)) as unrolledAdmins where g.name IS NOT NULL AND (explicitAdmins + unrolledAdmins) > 0 RETURN g.name,explicitAdmins,unrolledAdmins, explicitAdmins + unrolledAdmins as totalAdmins ORDER BY totalAdmins DESC ``` -- Find all other Rights Domain Users shouldn't have (author: [jeffmcjunkin](https://gist.github.com/jeffmcjunkin/7b4a67bb7dd0cfbfbd83768f3aa6eb12) ): +- Counts unrolled members of Tier-0 privileged AD groups (copy all query lines, as they are UNION ALL joined): ``` -MATCH p=(m:Group)-[r:Owns|WriteDacl|GenericAll|WriteOwner|ExecuteDCOM|GenericWrite|AllowedToDelegate|ForceChangePassword]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "ENTERPRISE ADMINS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DOMAIN ADMINS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "SCHEMA ADMIN" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "ACCOUNT OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "BACKUP OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "PRINT OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "SERVER OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DOMAIN CONTROLLERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "READ-ONLY DOMAIN CONTROLLERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "GROUP POLICY CREATOR OWNERS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "CRYPTOGRAPHIC OPERATORS" RETURN g.name AS GroupName, count(u) AS MembersCounted UNION ALL +MATCH (u)-[:MemberOf*1..]->(g:Group) WHERE g.name starts with "DISTRIBUTED COM USERS" RETURN g.name AS GroupName, count(u) AS MembersCounted +``` + +### Computers + +- Returns computer names and their operating system for statistics purposes +``` +MATCH (c:Computer) WHERE c.operatingsystem is not null RETURN c.name as Name, c.operatingsystem as OS +``` + +- Returns a summary report of machines grouped by their operating systems versions, along with number of machines running specific OS version: +``` +MATCH (c:Computer) WHERE c.operatingsystem is not null MATCH (n:Computer {operatingsystem: c.operatingsystem}) RETURN c.operatingsystem as OS, count(distinct n) AS Number ORDER BY Number DESC +``` + +- Returns non-DC computers that enable unconstrained delegation along with their LDAP DN paths and operating systems.: +``` +MATCH (c:Computer {unconstraineddelegation: True}), (g:Group) WHERE g.name starts with 'DOMAIN CONTROLLERS' MATCH (c) WHERE NOT (c)-[:MemberOf]->(g) RETURN c.name, c.distinguishedname, c.operatingsystem ``` - Riccardo Ancarani's cypher queries (src: [GPOPowerParser](https://github.com/RiccardoAncarani/GPOPowerParser)) useful for any lateral movement insights: @@ -319,13 +283,68 @@ MATCH (u1:Computer)-[:AdminTo]->(c1:Computer {signing: false}) RETURN u1.name, c MATCH (u2)-[:MemberOf*1..]->(g:Group)-[:AdminTo]->(c2 {signing: false}) RETURN u2.name, c2.name ``` - - Find all the users that can RDP into a machine where they have special privileges: +### GPOs + +- Print GPO names and their container paths: ``` -MATCH (u:User)-[:CanRDP]->(c:Computer) WITH u,c -OPTIONAL MATCH (u)-[:MemberOf*1..]->(g:Group)-[:CanRDP]->(c) WITH u,c -MATCH (u)-[:CanPrivesc]->(c) RETURN u.name, c.name +MATCH (n:GPO) return n.name,n.gpcpath ``` +- Pull GPOs linked to users being member of a specified group: +``` +MATCH p = (:GPO)-[:GpLink]->(d)-[:Contains*1..]->(u:User)-[:MemberOf*1..]->(g:Group {name:'GROUP_NAME@CONTOSO.LOCAL'}) RETURN p +``` + +- Print GPOs with interesting words in their names along with their container paths: +``` +unwind ["360totalsecurity", "access", "acronis", "adaware", "admin", "admin", "aegislab", "ahnlab", "alienvault", "altavista", "amsi", "anti-virus", "antivirus", "antiy", "apexone", "applock", "arcabit", "arcsight", "atm", "atp", "av", "avast", "avg", "avira", "baidu", "baiduspider", "bank", "barracuda", "bingbot", "bitdefender", "bluvector", "canary", "carbon", "carbonblack", "certificate", "check", "checkpoint", "citrix", "clamav", "code42", "comodo", "countercept", "countertack", "credential", "crowdstrike", "custom", "cyberark", "cybereason", "cylance", "cynet360", "cyren", "darktrace", "datadog", "defender", "druva", "drweb", "duckduckbot", "edr", "egambit", "emsisoft", "encase", "endgame", "ensilo", "escan", "eset", "exabot", "exception", "f-secure", "f5", "falcon", "fidelis", "fireeye", "firewall", "fix", "forcepoint", "forti", "fortigate", "fortil", "fortinet", "gdata", "gravityzone", "guard", "honey", "huntress", "identity", "ikarussecurity", "insight", "ivanti", "juniper", "k7antivirus", "k7computing", "kaspersky", "kingsoft", "kiosk", "laps", "lightcyber", "logging", "logrhythm", "lynx", "malwarebytes", "manageengine", "mass", "mcafee", "microsoft", "mj12bot", "msnbot", "nanoav", "nessus", "netwitness", "office365", "onedrive", "orion", "palo", "paloalto", "paloaltonetworks", "panda", "pass", "powershell", "proofpoint", "proxy", "qradar", "rdp", "rsa", "runasppl", "sandboxe", "sap", "scanner", "scanning", "sccm", "script", "secret", "secureage", "secureworks", "security", "sensitive", "sentinel", "sentinelone", "slurp", "smartcard", "sogou", "solarwinds", "sonicwall", "sophos", "splunk", "superantispyware", "symantec", "tachyon", "temporary", "tencent", "totaldefense", "transfer", "trapmine", "trend micro", "trendmicro", "trusteer", "trustlook", "uac", "vdi", "virusblokada", "virustotal", "virustotalcloud", "vpn", "vuln", "webroot", "whitelist", "wifi", "winrm", "workaround", "yubikey", "zillya", "zonealarm", "zscaler"] as word match (n:GPO) where toLower(n.name) CONTAINS toLower(word) RETURN word, n.name, n.description, n.gpcpath ORDER BY n.name +``` + + +### OUs + +- Returns a list of OUs along with their members count (source: [hausec.com](https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/) ) +``` +MATCH (o:OU)-[:Contains]->(c) RETURN o.name,o.guid, COUNT(c) ORDER BY COUNT(c) DESC +``` + +### Other + + +- Retrieves nodes having particular juicy keywords in their description properties: +``` +MATCH (n) WHERE n.description CONTAINS 'pass' RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'secret' RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'admin' RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'sensitive' RETURN n.name, n.description +``` + +- Show only owned nodes of the above ones: +``` +MATCH (n) WHERE n.description CONTAINS 'pass' and n.owned = TRUE RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'secret' and n.owned = TRUE RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'admin' and n.owned = TRUE RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS 'sensitive' and n.owned = TRUE RETURN n.name, n.description UNION +MATCH (n) WHERE n.description CONTAINS '\\' and n.owned = TRUE RETURN n.name, n.description +``` + +- Retrieves nodes that contain UNC paths to SMB shares in their description fields: +``` +MATCH (n) WHERE n.description CONTAINS '\\\\' RETURN n.name, n.description +``` + +- Print **Security Solutions** (think SIEM, EDRs, AVs, Anomaly detection systems, etc) deployed in the company by searching for keywords in _name, description, distinguishedname_ of all objects (User, Group, Computer, OU, ...) +``` +UNWIND ["360totalsecurity", "acronis", "adaware", "aegislab", "ahnlab", "alienvault", "altavista", "anti-virus", "antivirus", "antiy", "apexone", "arcabit", "arcsight", "attivo", "avast", "avg", "avira", "baidu", "baiduspider", "barracuda", "bingbot", "bitdefender", "bitdefender", "bluecoat", "bluvector", "canary", "carbon", "carbonblack", "carbonblack", "check", "checkpoint", "clamav", "code42", "comodo", "cortex", "countercept", "countertack", "crowdstrike", "cyberark", "cybereason", "cylance", "cynet360", "cyren", "darktrace", "datadog", "defender", "druva", "drweb", "duckduckbot", "edr", "egambit", "emsisoft", "encase", "endgame", "ensilo", "escan", "eset", "exabot", "f-secure", "f5", "falcon", "fidelis", "fireeye", "forcepoint", "fortigate", "fortil", "fortinet", "gdata", "gdata", "gravityzone", "honey", "huntress", "ia_archiver", "ikarussecurity", "ivanti", "juniper", "k7antivirus", "k7computing", "kaspersky", "kingsoft", "lightcyber", "lynx", "malwarebytes", "mcafee", "microsoft", "mj12bot", "morphisec", "msnbot", "nanoav", "nessus", "netwitness", "office365", "palo", "paloalto", "paloaltonetworks", "panda", "proofpoint", "qradar", "sandboxe", "scanner", "scanning", "secureage", "secureworks", "security", "sentinelone", "simplepie", "slurp", "sogou", "solarwinds", "sonicwall", "sophos", "splunk", "superantispyware", "symantec", "tachyon", "tencent", "totaldefense", "trapmine", "trend", "trendmicro", "trusteer", "trustlook", "virus", "virustotal", "virustotalcloud", "webroot", "zillya", "zonealarm", "zscaler"] AS word MATCH (n) WHERE toLower(n.name) CONTAINS toLower(word) OR toLower(n.description) CONTAINS toLower(word) OR toLower(n.distinguishedname) CONTAINS toLower(word) RETURN word as keyword, LABELS(n)[1] as type, n.name, n.description, n.distinguishedname ORDER BY n.name +``` + +- Find all other Rights Domain Users shouldn't have (author: [jeffmcjunkin](https://gist.github.com/jeffmcjunkin/7b4a67bb7dd0cfbfbd83768f3aa6eb12) ): +``` +MATCH p=(m:Group)-[r:Owns|WriteDacl|GenericAll|WriteOwner|ExecuteDCOM|GenericWrite|AllowedToDelegate|ForceChangePassword]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p +``` + +--- + ## CREATE Nodes and Edges - Mark nodes as Owned: @@ -380,7 +399,10 @@ DOMAIN USERS@WINDOMAIN.LOCAL - AdminTo -> SECWWKS1000000.WINDOMAIN.LOCAL - Gener DOMAIN USERS@WINDOMAIN.LOCAL - AdminTo -> SECWWKS1000000.WINDOMAIN.LOCAL - GenericAll -> GENARO_PARKER@WINDOMAIN.LOCAL - MemberOf -> GROUP POLICY CREATOR OWNERS@WINDOMAIN.LOCAL ``` -## Other sources of great Cypher Queries: +--- + +## Other sources of great Cypher Queries + - Hausec - https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/ - Jeffmcjunkin - https://gist.github.com/jeffmcjunkin/7b4a67bb7dd0cfbfbd83768f3aa6eb12 - seajaysec - https://gist.github.com/seajaysec/c7f0995b5a6a2d30515accde8513f77d \ No newline at end of file