mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
feat(threat-detection): Use IAM Identity for Cloudtrail Threat Detection instead of IP (#5166)
This commit is contained in:
+21
-8
@@ -39,14 +39,27 @@ class cloudtrail_threat_detection_enumeration(Check):
|
||||
minutes=threat_detection_minutes,
|
||||
):
|
||||
event_log = json.loads(event_log["CloudTrailEvent"])
|
||||
if ".amazonaws.com" not in event_log["sourceIPAddress"]:
|
||||
if event_log["sourceIPAddress"] not in potential_enumeration:
|
||||
potential_enumeration[event_log["sourceIPAddress"]] = set()
|
||||
potential_enumeration[event_log["sourceIPAddress"]].add(
|
||||
event_name
|
||||
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"],
|
||||
)
|
||||
for source_ip, actions in potential_enumeration.items():
|
||||
ip_threshold = round(len(actions) / len(enumeration_actions), 2)
|
||||
].add(event_name)
|
||||
|
||||
for aws_identity, actions in potential_enumeration.items():
|
||||
identity_threshold = round(len(actions) / len(enumeration_actions), 2)
|
||||
aws_identity_type = aws_identity[1]
|
||||
aws_identity_arn = aws_identity[0]
|
||||
if len(actions) / len(enumeration_actions) > threshold:
|
||||
found_potential_enumeration = True
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
@@ -56,7 +69,7 @@ class cloudtrail_threat_detection_enumeration(Check):
|
||||
cloudtrail_client.region
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Potential enumeration attack detected from source IP {source_ip} with an threshold of {ip_threshold}."
|
||||
report.status_extended = f"Potential enumeration attack detected from AWS {aws_identity_type} {aws_identity_arn.split('/')[-1]} with an threshold of {identity_threshold}."
|
||||
findings.append(report)
|
||||
if not found_potential_enumeration:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
|
||||
+22
-13
@@ -40,19 +40,28 @@ class cloudtrail_threat_detection_privilege_escalation(Check):
|
||||
minutes=threat_detection_minutes,
|
||||
):
|
||||
event_log = json.loads(event_log["CloudTrailEvent"])
|
||||
if ".amazonaws.com" not in event_log["sourceIPAddress"]:
|
||||
if (
|
||||
event_log["sourceIPAddress"]
|
||||
not in potential_privilege_escalation
|
||||
):
|
||||
potential_privilege_escalation[
|
||||
event_log["sourceIPAddress"]
|
||||
] = set()
|
||||
if (
|
||||
event_log["userIdentity"]["arn"],
|
||||
event_log["userIdentity"]["type"],
|
||||
) not in potential_privilege_escalation:
|
||||
potential_privilege_escalation[
|
||||
event_log["sourceIPAddress"]
|
||||
].add(event_name)
|
||||
for source_ip, actions in potential_privilege_escalation.items():
|
||||
ip_threshold = round(len(actions) / len(privilege_escalation_actions), 2)
|
||||
(
|
||||
event_log["userIdentity"]["arn"],
|
||||
event_log["userIdentity"]["type"],
|
||||
)
|
||||
] = set()
|
||||
potential_privilege_escalation[
|
||||
(
|
||||
event_log["userIdentity"]["arn"],
|
||||
event_log["userIdentity"]["type"],
|
||||
)
|
||||
].add(event_name)
|
||||
for aws_identity, actions in potential_privilege_escalation.items():
|
||||
identity_threshold = round(
|
||||
len(actions) / len(privilege_escalation_actions), 2
|
||||
)
|
||||
aws_identity_type = aws_identity[1]
|
||||
aws_identity_arn = aws_identity[0]
|
||||
if len(actions) / len(privilege_escalation_actions) > threshold:
|
||||
found_potential_privilege_escalation = True
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
@@ -62,7 +71,7 @@ class cloudtrail_threat_detection_privilege_escalation(Check):
|
||||
cloudtrail_client.region
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Potential privilege escalation attack detected from source IP {source_ip} with an threshold of {ip_threshold}."
|
||||
report.status_extended = f"Potential privilege escalation attack detected from AWS {aws_identity_type} {aws_identity_arn.split('/')[-1]} with an threshold of {identity_threshold}."
|
||||
findings.append(report)
|
||||
if not found_potential_privilege_escalation:
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
|
||||
+3
-3
@@ -19,10 +19,10 @@ def mock_get_trail_arn_template(region=None, *_) -> str:
|
||||
def mock__get_lookup_events__(trail=None, event_name=None, minutes=None, *_) -> list:
|
||||
return [
|
||||
{
|
||||
"CloudTrailEvent": '{"sourceIPAddress": "172.28.7.0/24", "eventName": "DescribeAccessEntry"}'
|
||||
"CloudTrailEvent": '{"eventName": "DescribeAccessEntry", "userIdentity": {"type": "IAMUser", "principalId": "EXAMPLE6E4XEGITWATV6R", "arn": "arn:aws:iam::123456789012:user/Mateo", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "userName": "Mateo", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
|
||||
},
|
||||
{
|
||||
"CloudTrailEvent": '{"sourceIPAddress": "172.28.7.0/24", "eventName": "DescribeAccountAttributes"}'
|
||||
"CloudTrailEvent": '{"eventName": "DescribeAccountAttributes", "userIdentity": {"type": "IAMUser", "principalId": "EXAMPLE6E4XEGITWATV6R", "arn": "arn:aws:iam::123456789012:user/Mateo", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "userName": "Mateo", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
|
||||
},
|
||||
]
|
||||
|
||||
@@ -154,7 +154,7 @@ class Test_cloudtrail_threat_detection_enumeration:
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Potential enumeration attack detected from source IP 172.28.7.0/24 with an threshold of 1.0."
|
||||
== "Potential enumeration attack detected from AWS IAMUser Mateo with an threshold of 1.0."
|
||||
)
|
||||
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
|
||||
+3
-3
@@ -19,10 +19,10 @@ def mock_get_trail_arn_template(region=None, *_) -> str:
|
||||
def mock__get_lookup_events__(trail=None, event_name=None, minutes=None, *_) -> list:
|
||||
return [
|
||||
{
|
||||
"CloudTrailEvent": '{"sourceIPAddress": "172.28.7.0/24", "eventName": "CreateLoginProfile"}'
|
||||
"CloudTrailEvent": '{"eventName": "CreateLoginProfile", "userIdentity": {"type": "IAMUser", "principalId": "EXAMPLE6E4XEGITWATV6R", "arn": "arn:aws:iam::123456789012:user/Mateo", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "userName": "Mateo", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
|
||||
},
|
||||
{
|
||||
"CloudTrailEvent": '{"sourceIPAddress": "172.28.7.0/24", "eventName": "UpdateLoginProfile"}'
|
||||
"CloudTrailEvent": '{"eventName": "UpdateLoginProfile", "userIdentity": {"type": "IAMUser", "principalId": "EXAMPLE6E4XEGITWATV6R", "arn": "arn:aws:iam::123456789012:user/Mateo", "accountId": "123456789012", "accessKeyId": "AKIAIOSFODNN7EXAMPLE", "userName": "Mateo", "sessionContext": {"sessionIssuer": {}, "webIdFederationData": {}, "attributes": {"creationDate": "2023-07-19T21:11:57Z", "mfaAuthenticated": "false"}}}}'
|
||||
},
|
||||
]
|
||||
|
||||
@@ -153,7 +153,7 @@ class Test_cloudtrail_threat_detection_privilege_escalation:
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Potential privilege escalation attack detected from source IP 172.28.7.0/24 with an threshold of 1.0."
|
||||
== "Potential privilege escalation attack detected from AWS IAMUser Mateo with an threshold of 1.0."
|
||||
)
|
||||
assert result[0].resource_id == AWS_ACCOUNT_NUMBER
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
|
||||
Reference in New Issue
Block a user