fix(threat detection): ignore AWS services events (#5276)

This commit is contained in:
Sergio Garcia
2024-10-07 14:25:09 -04:00
committed by GitHub
parent 2f8a3d2ef8
commit 3950d7eba8
4 changed files with 151 additions and 20 deletions
@@ -40,21 +40,24 @@ class cloudtrail_threat_detection_enumeration(Check):
):
event_log = json.loads(event_log["CloudTrailEvent"])
if (
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
) not in potential_enumeration:
"arn" in event_log["userIdentity"]
): # Ignore event logs without ARN since they are AWS services
if (
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
) not in potential_enumeration:
potential_enumeration[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
] = set()
potential_enumeration[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
] = set()
potential_enumeration[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
].add(event_name)
].add(event_name)
for aws_identity, actions in potential_enumeration.items():
identity_threshold = round(len(actions) / len(enumeration_actions), 2)
@@ -41,21 +41,24 @@ class cloudtrail_threat_detection_privilege_escalation(Check):
):
event_log = json.loads(event_log["CloudTrailEvent"])
if (
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
) not in potential_privilege_escalation:
"arn" in event_log["userIdentity"]
): # Ignore event logs without ARN since they are AWS services
if (
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
) not in potential_privilege_escalation:
potential_privilege_escalation[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
] = set()
potential_privilege_escalation[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
] = set()
potential_privilege_escalation[
(
event_log["userIdentity"]["arn"],
event_log["userIdentity"]["type"],
)
].add(event_name)
].add(event_name)
for aws_identity, actions in potential_privilege_escalation.items():
identity_threshold = round(
len(actions) / len(privilege_escalation_actions), 2
@@ -27,6 +27,19 @@ def mock__get_lookup_events__(trail=None, event_name=None, minutes=None, *_) ->
]
def mock__get_lookup_events_aws_service__(
trail=None, event_name=None, minutes=None, *_
) -> list:
return [
{
"CloudTrailEvent": '{"eventName": "DescribeAccessEntry", "userIdentity": {"type": "AWSService", "principalId": "EXAMPLE6E4XEGITWATV6R", "accountId": "123456789012", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
},
{
"CloudTrailEvent": '{"eventName": "DescribeAccountAttributes", "userIdentity": {"type": "AWSService", "principalId": "EXAMPLE6E4XEGITWATV6R", "accountId": "123456789012", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
},
]
class Test_cloudtrail_threat_detection_enumeration:
@mock_aws
def test_no_trails(self):
@@ -211,3 +224,52 @@ class Test_cloudtrail_threat_detection_enumeration:
result[0].resource_arn
== f"arn:aws:cloudtrail:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:trail"
)
@mock_aws
def test_potential_enumeration_from_aws_service(self):
ENUMERATION_ACTIONS = ["DescribeAccessEntry", "DescribeAccountAttributes"]
THRESHOLD = 2.0
THREAT_DETECTION_MINUTES = 1440
cloudtrail_client = mock.MagicMock()
cloudtrail_client.trails = {"us-east-1": mock.MagicMock()}
cloudtrail_client.trails["us-east-1"].is_multiregion = False
cloudtrail_client.trails["us-east-1"].name = "trail_test_us"
cloudtrail_client.trails["us-east-1"].s3_bucket_name = "bucket_test_us"
cloudtrail_client.trails["us-east-1"].region = "us-east-1"
cloudtrail_client.audited_account = AWS_ACCOUNT_NUMBER
cloudtrail_client.region = AWS_REGION_US_EAST_1
cloudtrail_client.audit_config = {
"threat_detection_enumeration_actions": ENUMERATION_ACTIONS,
"threat_detection_enumeration_threshold": THRESHOLD,
"threat_detection_enumeration_minutes": THREAT_DETECTION_MINUTES,
}
cloudtrail_client._lookup_events = mock__get_lookup_events_aws_service__
cloudtrail_client._get_trail_arn_template = mock_get_trail_arn_template
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_aws_provider(),
), mock.patch(
"prowler.providers.aws.services.cloudtrail.cloudtrail_threat_detection_enumeration.cloudtrail_threat_detection_enumeration.cloudtrail_client",
new=cloudtrail_client,
):
# Test Check
from prowler.providers.aws.services.cloudtrail.cloudtrail_threat_detection_enumeration.cloudtrail_threat_detection_enumeration import (
cloudtrail_threat_detection_enumeration,
)
check = cloudtrail_threat_detection_enumeration()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended == "No potential enumeration attack detected."
)
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert result[0].region == AWS_REGION_US_EAST_1
assert (
result[0].resource_arn
== f"arn:aws:cloudtrail:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:trail"
)
@@ -27,6 +27,19 @@ def mock__get_lookup_events__(trail=None, event_name=None, minutes=None, *_) ->
]
def mock__get_lookup_events_aws_service__(
trail=None, event_name=None, minutes=None, *_
) -> list:
return [
{
"CloudTrailEvent": '{"eventName": "CreateLoginProfile", "userIdentity": {"type": "AWSService", "principalId": "EXAMPLE6E4XEGITWATV6R", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
},
{
"CloudTrailEvent": '{"eventName": "UpdateLoginProfile", "userIdentity": {"type": "AWSService", "principalId": "EXAMPLE6E4XEGITWATV6R", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
},
]
class Test_cloudtrail_threat_detection_privilege_escalation:
@mock_aws
def test_no_trails(self):
@@ -211,3 +224,53 @@ class Test_cloudtrail_threat_detection_privilege_escalation:
result[0].resource_arn
== f"arn:aws:cloudtrail:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:trail"
)
@mock_aws
def test_potential_enumeration_from_aws_service(self):
cloudtrail_client = mock.MagicMock()
cloudtrail_client.trails = {"us-east-1": mock.MagicMock()}
cloudtrail_client.trails["us-east-1"].is_multiregion = False
cloudtrail_client.trails["us-east-1"].name = "trail_test_us"
cloudtrail_client.trails["us-east-1"].s3_bucket_name = "bucket_test_us"
cloudtrail_client.trails["us-east-1"].region = "us-east-1"
cloudtrail_client.audited_account = AWS_ACCOUNT_NUMBER
cloudtrail_client.region = AWS_REGION_US_EAST_1
cloudtrail_client.audit_config = {
"threat_detection_privilege_escalation_actions": [
"CreateLoginProfile",
"UpdateLoginProfile",
],
"threat_detection_privilege_escalation_threshold": 2.0,
"threat_detection_privilege_escalation_minutes": 1440,
}
cloudtrail_client._lookup_events = mock__get_lookup_events_aws_service__
cloudtrail_client._get_trail_arn_template = mock_get_trail_arn_template
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_aws_provider(),
), mock.patch(
"prowler.providers.aws.services.cloudtrail.cloudtrail_threat_detection_privilege_escalation.cloudtrail_threat_detection_privilege_escalation.cloudtrail_client",
new=cloudtrail_client,
):
# Test Check
from prowler.providers.aws.services.cloudtrail.cloudtrail_threat_detection_privilege_escalation.cloudtrail_threat_detection_privilege_escalation import (
cloudtrail_threat_detection_privilege_escalation,
)
check = cloudtrail_threat_detection_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "No potential privilege escalation attack detected."
)
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
assert result[0].region == AWS_REGION_US_EAST_1
assert (
result[0].resource_arn
== f"arn:aws:cloudtrail:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:trail"
)