-
Notifications
You must be signed in to change notification settings - Fork 8
/
BH Red2Blue.txt
235 lines (196 loc) · 7.92 KB
/
BH Red2Blue.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
***** DOMAIN USERS is Admin of Computer
MATCH p=(m:Group)-[:AdminTo]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p
*****
******* ShortestPath From Domain Users to Domain Admins
MATCH p=ShortestPath((n {name:"DOMAIN [email protected]"})
-[*1..]->(m {name: "DOMAIN [email protected]"}))
RETURN p
*******
******* Find Shortest Path from DOMAIN USERS to High Value Targets
MATCH (g:Group),(n {highvalue:true}),p=shortestPath((g)-[*1..]->(n))
WHERE g.name STARTS WITH 'DOMAIN USERS'
RETURN p
********
******* Find ALL Path from DOMAIN USERS to High Value Targets
MATCH (g:Group) WHERE g.name STARTS WITH 'DOMAIN USERS' MATCH (n {highvalue:true}),p=shortestPath((g)-[r*1..]->(n)) return p
*****
***** Find all other right Domain Users shouldn’t have
MATCH p=(m:Group)-[r:Owns|:WriteDacl|:GenericAll|:WriteOwner|:ExecuteDCOM|:GenericWrite|:AllowedToDelegate|:ForceChangePassword]->(n:Computer) WHERE m.name STARTS WITH 'DOMAIN USERS' RETURN p
*****
***** Domain Controller object ownership. (BHE #1)
MATCH (g:Group)
WHERE g.objectid ENDS WITH '-516'
MATCH p = (n:Base)-[:Owns]->(c:Computer)-[:MemberOf*1..]->(g)
RETURN p
*****
***** Kerberoastable Accounts
MATCH (n:User)WHERE n.hasspn=true RETURN n
*****
***** Kerberoastable Accounts member of High Value Group
MATCH (n:User)-[r:MemberOf]->(g:Group) WHERE g.highvalue=true AND n.hasspn=true RETURN n, g, r
******
****** Privileged kerberoastable users (BHE #2)
MATCH p = shortestPath((u:User {hasspn:true})-[*1..]->(g:Group))
WHERE g.objectid ENDS WITH '-512'
RETURN p
******
***** Domain Users group and other large groups having control of other objects (BHE #3)
MATCH p = (g:Group)-[{isacl:true}]->(m)
WHERE g.objectid ENDS WITH '-513'
RETURN p
*****
****** Find WORKSTATIONS where Domain Users can RDP To
match p=(g:Group)-[:CanRDP]->(c:Computer) where g.name STARTS WITH 'DOMAIN USERS' AND NOT c.operatingsystem CONTAINS 'Server' return p
*******
******* Find SERVERS where Domain Users can RDP To
match p=(g:Group)-[:CanRDP]->(c:Computer)
where g.name STARTS WITH 'DOMAIN USERS'
AND c.operatingsystem CONTAINS 'Server'
return p
*******
******* Top 10 Computers with Most Admins
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
*******
******* How many High Value Target a Node can reach
MATCH p = shortestPath((n)-[*1..]->(m {highvalue:true}))
WHERE NOT n = m
RETURN DISTINCT(m.name),LABELS(m)[0],COUNT(DISTINCT(n))
ORDER BY COUNT(DISTINCT(n)) DESC
*******
******* All DA Account Sessions
MATCH (n:User)-[:MemberOf]->(g:Group {name:"DOMAIN [email protected]"})
MATCH p = (c:Computer)-[:HasSession]->(n)
return p
********
******** DA Sessions to NON DC - NEW WORKING VERSION
MATCH (dc:Computer)-[:MemberOf*1..]->(g:Group)
WHERE g.name CONTAINS "DOMAIN CONTROLLERS"
WITH COLLECT(dc.name) as dcs
MATCH (c:Computer) WHERE NOT c.name in dcs
MATCH p=(c)-[:HasSession]->(n:User)-[:MemberOf]->(g:Group)
WHERE g.name STARTS WITH "DOMAIN ADMINS"
RETURN n.name as Username
********
******** Count on how many non DC machines DA have sessions - Original query by Waldo (Not working afaik) Probably missing a COLLECT after WITH
MATCH (c:Computer)-[:MemberOf*1..]->(g:Group)
WHERE g.objectsid ENDS WITH "-516"
WITH c.name as DomainControllers
MATCH p = (c2:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group)
WHERE g.objectsid ENDS WITH "-512" AND NOT c2.name in DomainControllers
RETURN DISTINCT(u.name),COUNT(DISTINCT(c2))
ORDER BY COUNT(DISTINCT(c2)) DESC
*********
********* EXCLUDE PATH (Edge) on the fly
MATCH (n:User),(m:Group {name:"DOMAIN [email protected]"}),
p=shortestPath((n)-[r*1..]->(m))
WHERE ALL(x in relationships(p) WHERE type(x) <> "AdminTo")
RETURN p
**********
********** Set SPN to a User
MATCH (n:User {name:"[email protected]"}) SET n.hasspn=true
**********
********** Add DOMAIN USERS as Admin to COMPxxxx
MERGE (n:Group {name:"DOMAIN [email protected]"}) WITH n MERGE (m:Computer {name:"COMP00673.TESTLAB.LOCAL"}) WITH n,m MERGE (n)-[:AdminTo]->(m)
**********
********** Test our New Relationship
MATCH p=(n:Group {name:"DOMAIN [email protected]"})-[r:AdminTo]->(m:Computer {name:"COMP00673.TESTLAB.LOCAL"})
RETURN p
********** Try to replace AdminTo by 1**
********** Delete a Relationship
MATCH p=(n:Group {name:"DOMAIN [email protected]"})-[r:AdminTo]->
(m:Computer {name:"COMP00673.TESTLAB.LOCAL"})
DELETE r
**********
********** Shortest Path from Domain Users to Domain Admins
MATCH (g:Group {name:"DOMAIN [email protected]"}),
(n {name:"DOMAIN [email protected]"}),
p=shortestPath((g)-[*1..]->(n))
return p
**********
********** Shortest Path from Domain Users to Domain Admins (No AdminTo)
MATCH (g:Group {name:"DOMAIN [email protected]"}),
(n {name:"DOMAIN [email protected]"}),
p=shortestPath((g)-[r*1..]->(n))
WHERE ALL(x in relationships(p) WHERE type(x) <> "AdminTo")
return p
**********
********** Find Admin Group not tagged highvalue
MATCH (g:Group)
WHERE g.name CONTAINS "ADMIN"
AND g.highvalue IS null
RETURN g.name
**********
********** Set Admin Group as highvalue
MATCH (g:Group)
WHERE g.name CONTAINS "ADMIN"
AND g.highvalue IS null
SET g.highvalue=true
**********
********** Remore Admin User highvalue
MATCH p=(g:Group {highvalue: true})<-[:MemberOf]-(u:User)
WHERE g.name CONTAINS "ADMIN"
SET g.highvalue = NULL
**********
If you want to enumerate all available properties :
Match (n:Computer) return properties(n)
********** List all computers with unconstraineddelegation
MATCH (c:Computer {unconstraineddelegation:true})
return c.name
**********
********** Computer where the most users can RDP to
MATCH (c:Computer)
OPTIONAL MATCH (u1:User)-[:CanRDP]->(c)
OPTIONAL MATCH (u2:User)-[:MemberOf*1..]->(:Group)-[:CanRDP]->(c)
WITH COLLECT(u1) + COLLECT(u2) as tempVar,c
UNWIND tempVar as users
RETURN c.name,COUNT(DISTINCT(users))
ORDER BY COUNT(DISTINCT(users)) DESC
**********
********** Average Length of Path
MATCH (g:Group {name:'DOMAIN [email protected]'})
MATCH p = shortestPath((u:User)-[r:AdminTo|MemberOf|HasSession*1..]->(g))
WITH EXTRACT(n in NODES(p) | LABELS(n)[0]) as pathNodes
WITH FILTER(x IN pathNodes WHERE x = "Computer") as filteredPathNodes
RETURN AVG(LENGTH(filteredPathNodes))
**********
MATCH (u:User)
MATCH (g:Group {highvalue: True})
MATCH p = shortestPath((u:User)-[*1..]->(g))
RETURN DISTINCT(u.name),u.enabled
order by u.name
********** Count how many Users have a path to DA
MATCH p=shortestPath((u:User)-[*1..]->
(m:Group {name: "DOMAIN [email protected]"}))
RETURN COUNT (DISTINCT(u))
**********
********** % of how many Users have a path to DA
OPTIONAL MATCH p=shortestPath((u:User)-[*1..]->
(m:Group {name: "DOMAIN [email protected]"}))
OPTIONAL MATCH (uT:User)
WITH COUNT (DISTINCT(uT)) as uTotal, COUNT (DISTINCT(u)) as uHasPath
RETURN uHasPath *100 / uTotal as Percent
**********
********** Find users WITHOUT a path to DA
MATCH (n:User),(m:Group) WHERE NOT EXISTS ((n)-[*]->(m {name:"DOMAIN [email protected]"})) RETURN n.name
********** WARNING - This is extremly long
********** Find High Value Users that are NOT in the Protected User group
MATCH (prot:User)-[:MemberOf*1..]->(g:Group)
WHERE g.name = "PROTECTED [email protected]"
WITH COLLECT(prot) AS protected_user
MATCH p = (np:User)-[:MemberOf*1..]->(m:Group)
WHERE m.highvalue = True AND NOT np IN protected_user
RETURN np
**********
********** Find "Easy To Exploit" Path to high value target from Owned
MATCH p=shortestpath((s:User {owned: true})-[:MemberOf|AdminTo|Owns|ForceChangePassword|AddMember*1..]->(t {highvalue: true}))
RETURN p
********** List all Account with the word Admin both on AD and AAD
match (au:AZUser)
where au.azname contains "ADMIN"
match (u:User)
where u.name contains "ADMIN"
WITH COLLECT(u.name) + COLLECT(au.azname) as temp
UNWIND temp as usernames
return usernames
********** List local accounts that can control AAD Accounts
match p=shortestpath((:User)-[*1..]->(:AZUser)) return p