|
16 | 16 | description="Detect EC2 instances with SSH exposed to the internet that can assume higher-privileged roles to read tagged sensitive S3 buckets despite bucket-level public access blocks.", |
17 | 17 | provider="aws", |
18 | 18 | cypher=f""" |
19 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
20 | | - YIELD node AS internet |
| 19 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
21 | 20 |
|
22 | 21 | MATCH path_s3 = (aws:AWSAccount {{id: $provider_uid}})--(s3:S3Bucket)--(t:AWSTag) |
23 | 22 | WHERE toLower(t.key) = toLower($tag_key) AND toLower(t.value) = toLower($tag_value) |
|
32 | 31 |
|
33 | 32 | MATCH path_assume_role = (ec2)-[p:STS_ASSUMEROLE_ALLOW*1..9]-(r:AWSRole) |
34 | 33 |
|
35 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, ec2) |
36 | | - YIELD rel AS can_access |
| 34 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(ec2) |
37 | 35 |
|
38 | 36 | UNWIND nodes(path_s3) + nodes(path_ec2) + nodes(path_role) + nodes(path_assume_role) as n |
39 | 37 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
181 | 179 | description="Find EC2 instances flagged as exposed to the internet within the selected account.", |
182 | 180 | provider="aws", |
183 | 181 | cypher=f""" |
184 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
185 | | - YIELD node AS internet |
| 182 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
186 | 183 |
|
187 | 184 | MATCH path = (aws:AWSAccount {{id: $provider_uid}})--(ec2:EC2Instance) |
188 | 185 | WHERE ec2.exposed_internet = true |
189 | 186 |
|
190 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, ec2) |
191 | | - YIELD rel AS can_access |
| 187 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(ec2) |
192 | 188 |
|
193 | 189 | UNWIND nodes(path) as n |
194 | 190 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
205 | 201 | description="Find internet-facing resources associated with security groups that allow inbound access from '0.0.0.0/0'.", |
206 | 202 | provider="aws", |
207 | 203 | cypher=f""" |
208 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
209 | | - YIELD node AS internet |
| 204 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
210 | 205 |
|
211 | 206 | // Match EC2 instances that are internet-exposed with open security groups (0.0.0.0/0) |
212 | 207 | MATCH path_ec2 = (aws:AWSAccount {{id: $provider_uid}})--(ec2:EC2Instance)--(sg:EC2SecurityGroup)--(ipi:IpPermissionInbound)--(ir:IpRange) |
213 | 208 | WHERE ec2.exposed_internet = true |
214 | 209 | AND ir.range = "0.0.0.0/0" |
215 | 210 |
|
216 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, ec2) |
217 | | - YIELD rel AS can_access |
| 211 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(ec2) |
218 | 212 |
|
219 | 213 | UNWIND nodes(path_ec2) as n |
220 | 214 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
231 | 225 | description="Find Classic Load Balancers exposed to the internet along with their listeners.", |
232 | 226 | provider="aws", |
233 | 227 | cypher=f""" |
234 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
235 | | - YIELD node AS internet |
| 228 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
236 | 229 |
|
237 | 230 | MATCH path = (aws:AWSAccount {{id: $provider_uid}})--(elb:LoadBalancer)--(listener:ELBListener) |
238 | 231 | WHERE elb.exposed_internet = true |
239 | 232 |
|
240 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, elb) |
241 | | - YIELD rel AS can_access |
| 233 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(elb) |
242 | 234 |
|
243 | 235 | UNWIND nodes(path) as n |
244 | 236 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
255 | 247 | description="Find ELBv2 load balancers exposed to the internet along with their listeners.", |
256 | 248 | provider="aws", |
257 | 249 | cypher=f""" |
258 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
259 | | - YIELD node AS internet |
| 250 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
260 | 251 |
|
261 | 252 | MATCH path = (aws:AWSAccount {{id: $provider_uid}})--(elbv2:LoadBalancerV2)--(listener:ELBV2Listener) |
262 | 253 | WHERE elbv2.exposed_internet = true |
263 | 254 |
|
264 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, elbv2) |
265 | | - YIELD rel AS can_access |
| 255 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(elbv2) |
266 | 256 |
|
267 | 257 | UNWIND nodes(path) as n |
268 | 258 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
279 | 269 | description="Given a public IP address, find the related AWS resource and its adjacent node within the selected account.", |
280 | 270 | provider="aws", |
281 | 271 | cypher=f""" |
282 | | - CALL apoc.create.vNode(['Internet'], {{id: 'Internet', name: 'Internet', provider_id: $provider_id}}) |
283 | | - YIELD node AS internet |
| 272 | + OPTIONAL MATCH (internet:Internet {{_provider_id: $provider_id}}) |
284 | 273 |
|
285 | | - CALL () {{ |
286 | | - MATCH path = (aws:AWSAccount {{id: $provider_uid}})-[r]-(x:EC2PrivateIp)-[q]-(y) |
287 | | - WHERE x.public_ip = $ip |
288 | | - RETURN path, x |
| 274 | + MATCH path = (aws:AWSAccount {{id: $provider_uid}})-[r]-(x)-[q]-(y) |
| 275 | + WHERE (x:EC2PrivateIp AND x.public_ip = $ip) |
| 276 | + OR (x:EC2Instance AND x.publicipaddress = $ip) |
| 277 | + OR (x:NetworkInterface AND x.public_ip = $ip) |
| 278 | + OR (x:ElasticIPAddress AND x.public_ip = $ip) |
289 | 279 |
|
290 | | - UNION MATCH path = (aws:AWSAccount {{id: $provider_uid}})-[r]-(x:EC2Instance)-[q]-(y) |
291 | | - WHERE x.publicipaddress = $ip |
292 | | - RETURN path, x |
293 | | -
|
294 | | - UNION MATCH path = (aws:AWSAccount {{id: $provider_uid}})-[r]-(x:NetworkInterface)-[q]-(y) |
295 | | - WHERE x.public_ip = $ip |
296 | | - RETURN path, x |
297 | | -
|
298 | | - UNION MATCH path = (aws:AWSAccount {{id: $provider_uid}})-[r]-(x:ElasticIPAddress)-[q]-(y) |
299 | | - WHERE x.public_ip = $ip |
300 | | - RETURN path, x |
301 | | - }} |
302 | | -
|
303 | | - WITH path, x, internet |
304 | | -
|
305 | | - CALL apoc.create.vRelationship(internet, 'CAN_ACCESS', {{provider_id: $provider_id}}, x) |
306 | | - YIELD rel AS can_access |
| 280 | + OPTIONAL MATCH (internet)-[can_access:CAN_ACCESS]->(x) |
307 | 281 |
|
308 | 282 | UNWIND nodes(path) as n |
309 | 283 | OPTIONAL MATCH (n)-[pfr]-(pf:{PROWLER_FINDING_LABEL} {{status: 'FAIL', provider_uid: $provider_uid}}) |
|
0 commit comments