Skip to content
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

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions rules/aws_s3_rules/aws_s3_bucket_defacement_attempt.py
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
Copy link
Contributor

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



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"),
}
82 changes: 82 additions & 0 deletions rules/aws_s3_rules/aws_s3_bucket_defacement_attempt.yml
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This detection should include test cases that show

  1. S3 Get operation which does not match the EXCLUDE_* rules -> false
  2. At least one test case demonstrating that the EXCLUDE_* functions -> false
  3. a s3 put operation which returns -> true. You'll need to mock the INCLUDED_BUCKET_NAMES object. I'm happy to help with that if you would like 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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:

rules/aws_s3_rules/aws_s3_bucket_defacement_attempt.py:22:0: R1260: 'rule' is too complex. The McCabe rating is 15 (too-complex)
rules/aws_s3_rules/aws_s3_bucket_defacement_attempt.py:22:0: R0911: Too many return statements (7/6) (too-many-return-statements)
rules/aws_s3_rules/aws_s3_bucket_defacement_attempt.py:22:0: R0912: Too many branches (14/12) (too-many-branches)

Are those thresholds arbitrary?

Copy link
Contributor

Choose a reason for hiding this comment

The 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