-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
s3 rule added to monitor potential defacement attempts #563
Changes from 5 commits
8b6decd
7f26d0a
ef16633
b62105d
6879187
3ed3bed
1910387
b7d0816
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
from fnmatch import fnmatch | ||
|
||
# Ignore certain operations, users, user agents and specifc iam roles | ||
EXCLUDED_OPERATIONS = ["REST.GET.*", "REST.HEAD.*", "S3.EXPIRE.OBJECT"] | ||
EXCLUDED_REQUESTERS = ["svc:*", "AmazonS3", "*:assumed-role/AWSServiceRole*", ""] | ||
EXCLUDED_USERAGENTS = ["*aws-internal*"] | ||
EXCLUDED_ASSUMED_ROLES = ["*assumed-role/pan*"] | ||
|
||
# Optionally, explicitly monitor specific buckets and/or files | ||
INCLUDED_BUCKET_NAMES = [] | ||
INCLUDED_S3_BUCKET_KEY = [] | ||
|
||
|
||
def rule(event): | ||
|
||
# Quick exit if event contains ignored value | ||
for item in EXCLUDED_OPERATIONS: | ||
if fnmatch(event.get("operation"), item): | ||
return False | ||
|
||
for item in EXCLUDED_REQUESTERS: | ||
if fnmatch(event.get("requester"), item): | ||
return False | ||
|
||
for item in EXCLUDED_USERAGENTS: | ||
if fnmatch(event.get("useragent"), item): | ||
return False | ||
|
||
for item in EXCLUDED_ASSUMED_ROLES: | ||
if fnmatch(event.get("requester"), item): | ||
return False | ||
|
||
for item in INCLUDED_BUCKET_NAMES: | ||
if fnmatch(event.get("bucket"), item): | ||
return True | ||
|
||
for item in INCLUDED_S3_BUCKET_KEY: | ||
if fnmatch(event.get("key"), item): | ||
return True | ||
|
||
return True | ||
|
||
|
||
def title(event): | ||
return f"Unexpected requester put [{event.get('key')}] in [{event.get('bucket')}]" | ||
|
||
|
||
def alert_context(event): | ||
return { | ||
"requester": event.get("requester"), | ||
"bucket": event.get("bucket"), | ||
"remoteip": event.get("remoteip"), | ||
"key": event.get("key"), | ||
"useragent": event.get("useragent"), | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
AnalysisType: rule | ||
Description: Adversaries may modify visual content available internally or externally to an enterprise network, thus affecting the integrity of the original content. Reasons for Defacement include delivering messaging, intimidation, or claiming (possibly false) credit for an intrusion. Disturbing or offensive images may be used as a part of Defacement in order to cause user discomfort, or to pressure compliance with accompanying messages. | ||
DisplayName: S3 Bucket Defacement Attempt | ||
Enabled: false | ||
Filename: aws_s3_bucket_defacement_attempt.py | ||
Reference: https://attack.mitre.org/techniques/T1491/ | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0040:T1491 | ||
Severity: Low | ||
Tests: | ||
- ExpectedResult: true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This detection should include test cases that show
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey hey! I made some changes and pushed them. However, it doesn't appear to pass linting:
Are those thresholds arbitrary? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those thresholds are intentional ( arbitrary is a word that might be universally applied to any style/lint guidelines ). There's ~1 detection that's disabling these by intention. I can take a look in here and see if there's a way to logically simplify the detection |
||
Log: | ||
authenticationtype: AuthHeader | ||
bucket: sample-bucket-name | ||
bucketowner: a5ebe8d8c26923db177773b444efba8fc3c87ee7416a2a7453c42b49eb66dcee | ||
ciphersuite: ECDHE-RSA-AES128-GCM-SHA256 | ||
hostheader: sample-bucket-name.s3.us-east-2.amazonaws.com | ||
hostid: r+TmRb3RpSpdyYMQQX/1OQKWO8duNRIT8jkARf0+5aInlIfkixImJwhoyzK+6nczpgOnIdIksBg= | ||
httpstatus: 200 | ||
key: layers/sample-file.zip | ||
objectsize: 6.022694e+06 | ||
operation: REST.PUT.OBJECT | ||
p_any_aws_arns: | ||
- arn:aws:sts::12345678910:assumed-role/sample-role | ||
p_any_ip_addresses: | ||
- 10.0.18.38 | ||
p_event_time: "2022-11-01 18:45:45" | ||
p_log_type: AWS.S3ServerAccess | ||
p_parse_time: "2022-11-01 19:17:50.353" | ||
p_row_id: ea9400dbc7b99c88a9b6ccac14d39201 | ||
p_source_id: 4a42e408-9e2d-4a55-9830-708b8286bc32 | ||
p_source_label: s3-sensitive-data | ||
remoteip: 10.0.18.38 | ||
requester: arn:aws:sts::12345678910:assumed-role/test-role | ||
requestid: 6NBZJ3SRYX5MPDX8 | ||
requesturi: PUT /layers/sample-file.zip HTTP/1.1 | ||
signatureversion: SigV4 | ||
time: "2022-11-01 18:45:45" | ||
tlsVersion: TLSv1.2 | ||
totaltime: 197 | ||
turnaroundtime: 96 | ||
useragent: aws-cli/1.20.58 Python/3.9.5 Linux/4.14.248-189.473.amzn2.aarch64 exec-env/AWS_ECS_EC2 botocore/1.21.58 | ||
Name: Defacement | ||
- ExpectedResult: false | ||
Log: | ||
authenticationtype: AuthHeader | ||
bucket: sample-bucket-name | ||
bucketowner: a5ebe8d8c26923db177773b444efba8fc3c87ee7416a2a7453c42b49eb66dcee | ||
ciphersuite: ECDHE-RSA-AES128-GCM-SHA256 | ||
hostheader: sample-bucket-name.s3.us-east-2.amazonaws.com | ||
hostid: r+TmRb3RpSpdyYMQQX/1OQKWO8duNRIT8jkARf0+5aInlIfkixImJwhoyzK+6nczpgOnIdIksBg= | ||
httpstatus: 200 | ||
key: layers/sample-file.zip | ||
objectsize: 6.022694e+06 | ||
operation: REST.GET.DUMMY | ||
p_any_aws_arns: | ||
- arn:aws:sts::12345678910:assumed-role/sample-role | ||
p_any_ip_addresses: | ||
- 10.0.18.38 | ||
p_event_time: "2022-11-01 18:45:45" | ||
p_log_type: AWS.S3ServerAccess | ||
p_parse_time: "2022-11-01 19:17:50.353" | ||
p_row_id: ea9400dbc7b99c88a9b6ccac14d39201 | ||
p_source_id: 4a42e408-9e2d-4a55-9830-708b8286bc32 | ||
p_source_label: s3-sensitive-data | ||
remoteip: 10.0.18.38 | ||
requester: arn:aws:sts::12345678910:assumed-role/test-role | ||
requestid: 6NBZJ3SRYX5MPDX8 | ||
requesturi: PUT /layers/sample-file.zip HTTP/1.1 | ||
signatureversion: SigV4 | ||
time: "2022-11-01 18:45:45" | ||
tlsVersion: TLSv1.2 | ||
totaltime: 197 | ||
turnaroundtime: 96 | ||
useragent: aws-cli/1.20.58 Python/3.9.5 Linux/4.14.248-189.473.amzn2.aarch64 exec-env/AWS_ECS_EC2 botocore/1.21.58 | ||
Name: Defacement - Excluded | ||
DedupPeriodMinutes: 60 | ||
LogTypes: | ||
- AWS.S3ServerAccess | ||
RuleID: AWS.S3.Defacement.Attempt | ||
Threshold: 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default should return
False
. When the default is True, lines 31-39 are unnecessary processing