Cypher Queries that Support Target Selection and Attacks
Count how many computers each user has admin access to
❓ Example: If a user is not a DA but has admin access to 1,000 computers, you might want to mark that user as a High Value Target.
Count the number of the computers where each domain user has direct Admin privileges:
MATCH (u:User)-[:AdminTo]->(c:Computer) RETURN count(DISTINCT(c.name)) AS COMPUTER, u.name AS USER ORDER BY count(DISTINCT(c.name)) DESC
Count the number of the computers where each domain user has derivative Admin privileges:
MATCH (u:User)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c:Computer) RETURN count(DISTINCT(c.name)) AS COMPUTER, u.name AS USER ORDER BY count(DISTINCT(c.name)) DESC
Cyper Queries that Support Kerberoasting
Cracking SPN/Kerberoasted hashes is slow AF. Consider using these to help prioritize which SPNs to target for cracking.
List all Kerberoastable users that are members of High Value Target groups:
- DA’s in here? That’s a findin.’
MATCH p=shortestPath((n:User)-[:MemberOf]->(g:Group)) WHERE g.highvalue=true AND n.hasspn=true RETURN n.name AS Kerberoastable_User,g.name AS Privileged_Group
List all Kerberoastable users whose password was last changed BEFORE 2010-01-01:
- Reasoning: Service accounts probably don’t have their passwords changed very frequently (expected), but passwords from 11+ years ago are likely to be way weaker than today’s passwords.
- If you don’t get any hits, adjust the epoch time. LINK
MATCH (u:User {hasspn: true}) WHERE u.pwdlastset < 1262304000 RETURN u.name,u.pwdlastset
Find Linux hosts
MATCH (c:Computer {enabled: True}) WHERE ( c.name =~ '(?i).*(lin|nix|redhat|centos|ubuntu|deb).*' OR c.operatingsystem =~ '(?i).*(lin|nix|redhat|centos|ubuntu|deb).*' OR c.description =~ '(?i).*(linux|redhat|centos|ubuntu|debian).*' ) RETURN c.name as Computer, c.operatingsystem AS OS, c.description AS Description
Find interesting hosts where you can RDP
Hosts with details where all users can RDP:
- Very fast query
MATCH p=(g:Group)-[:CanRDP]->(c:Computer) WHERE g.name =~ '(?i)DOMAIN USERS.*' RETURN g.name AS Group_Name,c.name AS Computer_Name,c.description AS Description,c.enabled AS Enabled, c.operatingsystem AS Operating_SystemCount of computers where each owned user has RDP access:
MATCH p = allShortestPaths((o {owned:true})-[r:CanRDP|MemberOf*1..]->(c:Computer)) RETURN o.name AS Owned_Object, count(DISTINCT(c.name)) AS Computers_with_RDP_AccessFull list and details of computers where owned users can RDP:
MATCH p = allShortestPaths((o {owned:true})-[r:CanRDP|MemberOf*1..]->(c:Computer)) RETURN o.name AS Owned_Object, c.name AS Computer_Name, c.description AS Description, c.enabled AS Enabled, c.operatingsystem AS Operating_System