# Advanced BloodHound Queries Collection This document contains a comprehensive collection of queries for use with BloodHound, organized by category. These queries can help you analyze Active Directory environments more effectively. ## User and Group Analysis ### Find all edges any owned user has on a computer ``` MATCH p=shortestPath((m:User)-[r]->(b:Computer)) WHERE m.owned RETURN p ``` ### Find all Kerberoastable Users ``` MATCH (n:User) WHERE n.hasspn=true RETURN n ``` ### Find Kerberoastable Users with passwords last set > 5 years ago ``` MATCH (u:User) WHERE u.hasspn=true AND u.pwdlastset < (datetime().epochseconds - (1825 * 86400)) AND NOT u.pwdlastset IN [-1.0, 0.0] RETURN u.name, u.pwdlastset ORDER BY u.pwdlastset ``` ### Find users that logged in within the last 90 days ``` MATCH (u:User) WHERE u.lastlogon < (datetime().epochseconds - (90 * 86400)) AND NOT u.lastlogon IN [-1.0, 0.0] RETURN u.name, u.lastlogon ORDER BY u.lastlogon ``` ### List users and their login times + password last set times in human-readable format ``` MATCH (n:User) WHERE n.enabled = TRUE RETURN n.name, datetime({epochSeconds: toInteger(n.pwdlastset)}) as PwdLastSet, datetime({epochSeconds: toInteger(n.lastlogon)}) as LastLogon ORDER BY n.pwdlastset ``` ### Find users that have never logged on and account is still active ``` MATCH (n:User) WHERE n.lastlogontimestamp=-1.0 AND n.enabled=TRUE RETURN n.name ORDER BY n.name ``` ## Computer and Session Analysis ### Find computers with unconstrained delegation that AREN'T domain controllers ``` MATCH (c1:Computer)-[:MemberOf*1..]->(g:Group) WHERE g.objectsid ENDS WITH '-516' WITH COLLECT(c1.name) AS domainControllers MATCH (c2:Computer {unconstraineddelegation:true}) WHERE NOT c2.name IN domainControllers RETURN c2.name, c2.operatingsystem ORDER BY c2.name ASC ``` ### Find active Domain Admin sessions ``` MATCH (n:User)-[:MemberOf*1..]->(g:Group) WHERE g.objectid ENDS WITH '-512' MATCH p = (c:Computer)-[:HasSession]->(n) RETURN p ``` ### Find computers with descriptions ``` MATCH (c:Computer) WHERE c.description IS NOT NULL RETURN c.name, c.description ``` ## Domain and Forest Analysis ### Find connections between different domains/forests ``` MATCH (n)-[r]->(m) WHERE NOT n.domain = m.domain RETURN LABELS(n)[0], n.name, TYPE(r), LABELS(m)[0], m.name ``` ## Privilege and Access Analysis ### Find the percentage of computers with a path to Domain Admins ``` MATCH (totalComputers:Computer {domain:'DOMAIN.GR'}) MATCH p=shortestPath((ComputersWithPath:Computer {domain:'DOMAIN.GR'})-[r*1..]->(g:Group {name:'DOMAIN ADMINS@DOMAIN.GR'})) WITH COUNT(DISTINCT(totalComputers)) as totalComputers, COUNT(DISTINCT(ComputersWithPath)) as ComputersWithPath RETURN 100.0 * ComputersWithPath / totalComputers AS percentComputersToDA ``` ### Find the most privileged groups on the domain ``` 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 ``` ## Kerberos and Delegation Analysis ### Find users with constrained delegation permissions ``` MATCH (u:User) WHERE u.allowedtodelegate IS NOT NULL RETURN u.name, u.allowedtodelegate ``` ### Find computers with constrained delegation permissions ``` MATCH (c:Computer) WHERE c.allowedtodelegate IS NOT NULL RETURN c.name, c.allowedtodelegate ``` ## GPO and OU Analysis ### View OUs based on member count ``` MATCH (o:OU)-[:Contains]->(c:Computer) RETURN o.name, o.guid, COUNT(c) ORDER BY COUNT(c) DESC ``` ### Find if any domain user has interesting permissions against a GPO ``` MATCH p=(u:User)-[r:AllExtendedRights|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|GpLink*1..]->(g:GPO) RETURN p LIMIT 25 ``` ## ACL and Permission Analysis ### Find what permissions Everyone/Authenticated Users/Domain Users/Domain Computers have ``` MATCH p=(m:Group)-[r:AddMember|AdminTo|AllExtendedRights|AllowedToDelegate|CanRDP|Contains|ExecuteDCOM|ForceChangePassword|GenericAll|GenericWrite|GetChanges|GetChangesAll|HasSession|Owns|ReadLAPSPassword|SQLAdmin|TrustedBy|WriteDACL|WriteOwner|AddAllowedToAct|AllowedToAct]->(t) WHERE m.objectsid ENDS WITH '-513' OR m.objectsid ENDS WITH '-515' OR m.objectsid ENDS WITH 'S-1-5-11' OR m.objectsid ENDS WITH 'S-1-1-0' RETURN m.name, TYPE(r), t.name, t.enabled ``` ## Miscellaneous Queries ### Adjust Query to Local Timezone (Change timezone parameter) ``` MATCH (u:User) WHERE NOT u.lastlogon IN [-1.0, 0.0] RETURN u.name, datetime({epochSeconds:toInteger(u.lastlogon), timezone: '+10:00'}) as LastLogon ``` ### Find users that are part of the VPN group ``` MATCH (u:User)-[:MemberOf]->(g:Group) WHERE g.name CONTAINS "VPN" RETURN u.name, g.name ```