diff --git a/correlation_rules/aws_create_admin_iam_user.yml b/correlation_rules/aws_create_admin_iam_user.yml new file mode 100644 index 000000000..32f55a9e1 --- /dev/null +++ b/correlation_rules/aws_create_admin_iam_user.yml @@ -0,0 +1,62 @@ +AnalysisType: correlation_rule +RuleID: "AWS.Administrative.IAM.User.Created" +DisplayName: "AWS.Administrative.IAM.User.Created" +Enabled: true +Severity: High +Description: Identifies when an Administrative IAM user is creates. This could indicate a potential security breach. +Reference: https://stratus-red-team.cloud/attack-techniques/AWS/aws.persistence.iam-create-admin-user/ +Reports: + MITRE ATT&CK: + - TA0006:T1078 +Detection: + - Sequence: + - ID: CreateUser + RuleID: AWS.IAM.CreateUser + - ID: AttachAdminUserPolicy + RuleID: AWS.IAM.AttachAdminUserPolicy + Transitions: + - ID: CreateUser FOLLOWED BY AttachAdminUserPolicy + From: CreateUser + To: AttachAdminUserPolicy + WithinTimeFrameMinutes: 60 + Match: + - On: p_alert_context.request_username + LookbackWindowMinutes: 2160 + Schedule: + RateMinutes: 1440 + TimeoutMinutes: 5 +Tests: + - Name: User Created, Followed By Admin Policy Attachment + ExpectedResult: true + RuleOutputs: + - ID: CreateUser + Matches: + p_alert_context.request_username: + 'new-user': + - "2024-06-01T10:00:01Z" + - ID: AttachAdminUserPolicy + Matches: + p_alert_context.request_username: + 'new-user': + - "2024-06-01T11:00:01Z" + - Name: User Created, Not Followed By Admin Policy Attachment + ExpectedResult: false + RuleOutputs: + - ID: CreateUser + Matches: + p_alert_context.request_username: + 'new-user': + - "2024-06-01T10:00:01Z" + - Name: Wrong match + ExpectedResult: false + RuleOutputs: + - ID: CreateUser + Matches: + p_alert_context.request_username: + 'new-user': + - "2024-06-01T10:00:01Z" + - ID: AttachAdminUserPolicy + Matches: + p_alert_context.request_username: + 'not-new-user': + - "2024-06-01T11:00:01Z" \ No newline at end of file diff --git a/correlation_rules/aws_create_backdoor_admin_iam_role.yml b/correlation_rules/aws_create_backdoor_admin_iam_role.yml new file mode 100644 index 000000000..813f89f8c --- /dev/null +++ b/correlation_rules/aws_create_backdoor_admin_iam_role.yml @@ -0,0 +1,49 @@ +AnalysisType: correlation_rule +RuleID: "AWS.Backdoor.Administrative.IAM.Role.Created" +DisplayName: "AWS Backdoor Administrative IAM Role Created" +Enabled: true +Severity: High +Description: Identifies when CreateRole and AttachAdminRolePolicy CloudTrail events occur in a short period of time. This sequence could indicate a potential security breach. +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html +Reports: + MITRE ATT&CK: + - TA0007:T1078 +Detection: + - Sequence: + - ID: CreateRole + RuleID: AWS.IAM.CreateRole + - ID: AttachAdminRolePolicy + RuleID: AWS.IAM.AttachAdminRolePolicy + Transitions: + - ID: CreateRole FOLLOWED BY AttachAdminRolePolicy + From: CreateRole + To: AttachAdminRolePolicy + WithinTimeFrameMinutes: 60 + Match: + - On: p_alert_context.request_rolename + LookbackWindowMinutes: 2160 + Schedule: + RateMinutes: 1440 + TimeoutMinutes: 5 +Tests: + - Name: Role Created, Followed By Policy Attachment + ExpectedResult: true + RuleOutputs: + - ID: CreateRole + Matches: + p_alert_context.request_rolename: + 'new-role': + - "2024-06-01T10:00:01Z" + - ID: AttachAdminRolePolicy + Matches: + p_alert_context.request_rolename: + 'new-role': + - "2024-06-01T10:30:01Z" + - Name: Role Created, Not Followed By Policy Attachment + ExpectedResult: false + RuleOutputs: + - ID: CreateRole + Matches: + p_alert_context.request_rolename: + 'new-role': + - "2024-06-01T10:00:01Z" \ No newline at end of file diff --git a/packs/aws.yml b/packs/aws.yml index bef34bc9c..d9056ddca 100644 --- a/packs/aws.yml +++ b/packs/aws.yml @@ -64,6 +64,7 @@ PackDefinition: - AWS.CloudTrail.Password.Policy.Discovery - AWS.Console.LoginWithoutMFA - AWS.EC2.SecurityGroupModified + - AWS.IAM.BackdoorRole - AWS.IAM.Backdoor.User.Keys - AWS.IAM.CredentialsUpdated - AWS.IAM.Entity.InlinePolicyDoesNotGrantNetworkAdminAccess @@ -79,7 +80,6 @@ PackDefinition: - AWS.PasswordPolicy.PasswordReuse - AWS.Potentially.Stolen.Service.Role.Scheduled - AWS.Suspicious.SAML.Activity - - AWS.User.Login.Profile.Modified # General Policies and Rules - Amazon.EKS.Audit.Multiple403 - Amazon.EKS.Audit.SystemNamespaceFromPublicIP @@ -188,6 +188,8 @@ PackDefinition: - VPC.DNS.Tunneling - VPCFlow.Port.Scanning # Correlation Rules + - AWS.Administrative.IAM.User.Created + - AWS.Backdoor.Administrative.IAM.Role.Created - AWS.Privilege.Escalation.Via.User.Compromise - AWS.CloudTrail.SES.SESEnumeration - AWS.SSO.Access.Token.Retrieved.by.Unauthenticated.IP @@ -198,6 +200,10 @@ PackDefinition: - AWS.CloudTrail.UserAccessKeyAuth - AWS.CloudTrail.LoginProfileCreatedOrModified - AWS.Console.Login + - AWS.IAM.AttachAdminRolePolicy + - AWS.IAM.AttachAdminUserPolicy + - AWS.IAM.CreateRole + - AWS.IAM.CreateUser - AWS.CloudTrail.SES.CheckSESSendingEnabled - AWS.CloudTrail.SES.CheckSendQuota - AWS.CloudTrail.SES.ListIdentities diff --git a/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.py b/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.py index 3921e4c4f..2c109cb0d 100644 --- a/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.py +++ b/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.py @@ -1,20 +1,23 @@ -from panther_aws_helpers import aws_rule_context +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context PROFILE_EVENTS = { "UpdateLoginProfile", "CreateLoginProfile", + "DeleteLoginProfile", } def rule(event): # Only look for successes - if event.get("errorCode") or event.get("errorMessage"): + if not aws_cloudtrail_success(event): return False # Check when someone other than the user themselves creates or modifies a login profile + # with no password reset needed return ( event.get("eventSource", "") == "iam.amazonaws.com" and event.get("eventName", "") in PROFILE_EVENTS + and not event.deep_get("requestParameters", "passwordResetRequired", default=False) and not event.deep_get("userIdentity", "arn", default="").endswith( f"/{event.deep_get('requestParameters', 'userName', default='')}" ) diff --git a/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.yml b/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.yml index a1e2c115a..345fc4bac 100644 --- a/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.yml +++ b/rules/aws_cloudtrail_rules/aws_cloudtrail_loginprofilecreatedormodified.yml @@ -20,74 +20,74 @@ Tests: - Name: ChangeOwnPassword ExpectedResult: false Log: - awsRegion: us-east-1 - eventCategory: Management - eventID: "1234" - eventName: UpdateLoginProfile - eventSource: iam.amazonaws.com - eventTime: "2022-09-15 13:45:24" - eventType: AwsApiCall - eventVersion: "1.08" - managementEvent: true - readOnly: false - recipientAccountId: "987654321" - requestParameters: - passwordResetRequired: false - userName: alice - sessionCredentialFromConsole: true - sourceIPAddress: AWS Internal - userAgent: AWS Internal - userIdentity: - accessKeyId: ABC1234 - accountId: "987654321" - arn: arn:aws:sts::98765432:assumed-role/IAM/alice - principalId: ABCDE:alice - sessionContext: - attributes: - creationDate: "2022-09-15T13:36:47Z" - mfaAuthenticated: "true" - sessionIssuer: - accountId: "987654321" - arn: arn:aws:iam::9876432:role/IAM - principalId: 1234ABC - type: Role - userName: IAM - webIdFederationData: {} - type: AssumedRole + { "awsRegion": "us-east-1", + "eventCategory": "Management", + "eventID": "1234", + "eventName": "UpdateLoginProfile", + "eventSource": "iam.amazonaws.com", + "eventTime": "2022-09-15 13:45:24", + "eventType": "AwsApiCall", + "eventVersion": "1.08", + "managementEvent": true, + "readOnly": false, + "recipientAccountId": "987654321", + "requestParameters": + { "passwordResetRequired": false, + "userName": "alice" }, + "sessionCredentialFromConsole": true, + "sourceIPAddress": "AWS Internal", + "userAgent": "AWS Internal", + "userIdentity": + { "accessKeyId": "ABC1234", + "accountId": "987654321", + "arn": "arn:aws:sts::98765432:assumed-role/IAM/alice", + "principalId": "ABCDE:alice", + "sessionContext": + { "attributes": + { "creationDate": "2022-09-15T13:36:47Z", + "mfaAuthenticated": "true" }, + "sessionIssuer": + { "accountId": "987654321", + "arn": "arn:aws:iam::9876432:role/IAM", + "principalId": "1234ABC", + "type": "Role", + "userName": "IAM" }, + "webIdFederationData": { } }, + "type": "AssumedRole" } } - Name: User changed password for other ExpectedResult: true Log: - awsRegion: us-east-1 - eventCategory: Management - eventID: "1234" - eventName: UpdateLoginProfile - eventSource: iam.amazonaws.com - eventTime: "2022-09-15 13:45:24" - eventType: AwsApiCall - eventVersion: "1.08" - managementEvent: true - readOnly: false - recipientAccountId: "987654321" - requestParameters: - passwordResetRequired: false - userName: bob - sessionCredentialFromConsole: true - sourceIPAddress: AWS Internal - userAgent: AWS Internal - userIdentity: - accessKeyId: ABC1234 - accountId: "987654321" - arn: arn:aws:sts::98765432:assumed-role/IAM/alice - principalId: ABCDE:alice - sessionContext: - attributes: - creationDate: "2022-09-15T13:36:47Z" - mfaAuthenticated: "true" - sessionIssuer: - accountId: "987654321" - arn: arn:aws:iam::9876432:role/IAM - principalId: 1234ABC - type: Role - userName: IAM - webIdFederationData: {} - type: AssumedRole + { "awsRegion": "us-east-1", + "eventCategory": "Management", + "eventID": "1234", + "eventName": "UpdateLoginProfile", + "eventSource": "iam.amazonaws.com", + "eventTime": "2022-09-15 13:45:24", + "eventType": "AwsApiCall", + "eventVersion": "1.08", + "managementEvent": true, + "readOnly": false, + "recipientAccountId": "987654321", + "requestParameters": + { "passwordResetRequired": false, + "userName": "bob" }, + "sessionCredentialFromConsole": true, + "sourceIPAddress": "AWS Internal", + "userAgent": "AWS Internal", + "userIdentity": + { "accessKeyId": "ABC1234", + "accountId": "987654321", + "arn": "arn:aws:sts::98765432:assumed-role/IAM/alice", + "principalId": "ABCDE:alice", + "sessionContext": + { "attributes": + { "creationDate": "2022-09-15T13:36:47Z", + "mfaAuthenticated": "true" }, + "sessionIssuer": + { "accountId": "987654321", + "arn": "arn:aws:iam::9876432:role/IAM", + "principalId": "1234ABC", + "type": "Role", + "userName": "IAM" }, + "webIdFederationData": { } }, + "type": "AssumedRole" } } diff --git a/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.py b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.py new file mode 100644 index 000000000..e4f871c1a --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.py @@ -0,0 +1,18 @@ +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context + + +def rule(event): + if not aws_cloudtrail_success(event) or event.get("eventName") != "AttachRolePolicy": + return False + + policy = event.deep_get("requestParameters", "policyArn", default="POLICY_NOT_FOUND") + + return policy.endswith("AdministratorAccess") + + +def alert_context(event): + context = aws_rule_context(event) + context["request_rolename"] = event.deep_get( + "requestParameters", "roleName", default="ROLENAME_NOT_FOUND" + ) + return context diff --git a/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.yml b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.yml new file mode 100644 index 000000000..afffb43a8 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_role_policy.yml @@ -0,0 +1,115 @@ +AnalysisType: rule +Filename: aws_iam_attach_admin_role_policy.py +RuleID: "AWS.IAM.AttachAdminRolePolicy" +DisplayName: "IAM Administrator Role Policy Attached" +Enabled: true +LogTypes: + - AWS.CloudTrail +CreateAlert: false +Reports: + CIS: + - 1.1 + MITRE ATT&CK: + - TA0007:T1078 +Severity: Info +Description: > + An IAM role policy was attached with Administrator Access, which could indicate a potential security risk. +Runbook: Check if the action was expected. If not, remove the policy from the role. +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html +Tests: + - Name: IAM Role Policy Attached with Administrator Access + ExpectedResult: true + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachRolePolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/AdministratorAccess", + "roleName": "new-role" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM Role Policy Attached without Administrator Access + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachRolePolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/ReadOnlyAccess", + "roleName": "new-role" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } \ No newline at end of file diff --git a/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.py b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.py new file mode 100644 index 000000000..50ebd83b6 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.py @@ -0,0 +1,18 @@ +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context + + +def rule(event): + if not aws_cloudtrail_success(event) or event.get("eventName") != "AttachUserPolicy": + return False + + policy = event.deep_get("requestParameters", "policyArn", default="POLICY_NOT_FOUND") + + return policy.endswith("AdministratorAccess") + + +def alert_context(event): + context = aws_rule_context(event) + context["request_username"] = event.deep_get( + "requestParameters", "userName", default="USERNAME_NOT_FOUND" + ) + return context diff --git a/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.yml b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.yml new file mode 100644 index 000000000..024be3faf --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_attach_admin_user_policy.yml @@ -0,0 +1,115 @@ +AnalysisType: rule +Filename: aws_iam_attach_admin_user_policy.py +RuleID: "AWS.IAM.AttachAdminUserPolicy" +DisplayName: "IAM User Policy Attached with Administrator Access" +Enabled: true +CreateAlert: false +LogTypes: + - AWS.CloudTrail +Reports: + CIS: + - 1.1 + MITRE ATT&CK: + - TA0007:T1078 +Severity: Info +Description: > + An IAM user policy was attached with Administrator Access, which could indicate a potential security risk. +Runbook: Check if the user policy was attached by an authorized user. If not, investigate the user policy attachment. +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html +Tests: + - Name: IAM User Policy Attached with Administrator Access + ExpectedResult: true + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachUserPolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/AdministratorAccess", + "userName": "new-user" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM User Policy Attached without Administrator Access + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachUserPolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/ReadOnlyAccess", + "userName": "new-user" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } \ No newline at end of file diff --git a/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.py b/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.py new file mode 100644 index 000000000..476f58b38 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.py @@ -0,0 +1,17 @@ +import json + +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context +from policyuniverse.policy import Policy + + +def rule(event): + if not aws_cloudtrail_success(event) or event.get("eventName") != "UpdateAssumeRolePolicy": + return False + + policy = event.deep_get("requestParameters", "policyDocument", default="{}") + + return Policy(json.loads(policy)).is_internet_accessible() + + +def alert_context(event): + return aws_rule_context(event) diff --git a/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.yml b/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.yml new file mode 100644 index 000000000..3b51c78ff --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_backdoor_role.yml @@ -0,0 +1,161 @@ +AnalysisType: rule +Filename: aws_iam_backdoor_role.py +RuleID: "AWS.IAM.BackdoorRole" +DisplayName: "IAM Role Policy Updated to Allow Internet Access" +Enabled: true +LogTypes: + - AWS.CloudTrail +Tags: + - AWS + - Security Control + - IAM +Reports: + CIS: + - 1.1 + MITRE ATT&CK: + - TA0007:T1078 +Severity: Medium +Description: > + An IAM role policy was updated to allow internet access, which could indicate a backdoor. +Runbook: Check if the action was authorized and if the policy was updated by a trusted user. If not, revert the policy and investigate the user +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html +Tests: + - Name: IAM Role Policy Updated to Allow Internet Access + ExpectedResult: true + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "UpdateAssumeRolePolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"sts:AssumeRole\",\"Condition\":{\"StringEquals\":{\"sts:ExternalId\":\"12345\"}}}]}" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM Role Policy Updated Without Internet Access + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "UpdateAssumeRolePolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM Role Policy Updated With No Policy Document + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": { }, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "UpdateAssumeRolePolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + {}, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } \ No newline at end of file diff --git a/rules/aws_cloudtrail_rules/aws_iam_create_role.py b/rules/aws_cloudtrail_rules/aws_iam_create_role.py new file mode 100644 index 000000000..31a21656a --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_create_role.py @@ -0,0 +1,13 @@ +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context + + +def rule(event): + return aws_cloudtrail_success(event) and event.get("eventName") == "CreateRole" + + +def alert_context(event): + context = aws_rule_context(event) + context["request_rolename"] = event.deep_get( + "requestParameters", "roleName", default="ROLENAME_NOT_FOUND" + ) + return context diff --git a/rules/aws_cloudtrail_rules/aws_iam_create_role.yml b/rules/aws_cloudtrail_rules/aws_iam_create_role.yml new file mode 100644 index 000000000..b9d89d5f5 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_create_role.yml @@ -0,0 +1,114 @@ +AnalysisType: rule +Filename: aws_iam_create_role.py +RuleID: "AWS.IAM.CreateRole" +DisplayName: "IAM Role Created" +Enabled: true +LogTypes: + - AWS.CloudTrail +CreateAlert: false +Reports: + CIS: + - 1.1 + MITRE ATT&CK: + - TA0007:T1078 +Severity: Info +Description: > + An IAM role was created. +Runbook: Check if the action was expected. +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html +Tests: + - Name: IAM Role Created + ExpectedResult: true + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "CreateRole", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "roleName": "new-role" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM Role Not Created + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachUserPolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/AdministratorAccess", + "userName": "new-user" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } \ No newline at end of file diff --git a/rules/aws_cloudtrail_rules/aws_iam_create_user.py b/rules/aws_cloudtrail_rules/aws_iam_create_user.py new file mode 100644 index 000000000..43ae1e5f3 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_create_user.py @@ -0,0 +1,13 @@ +from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context + + +def rule(event): + return aws_cloudtrail_success(event) and event.get("eventName") == "CreateUser" + + +def alert_context(event): + context = aws_rule_context(event) + context["request_username"] = event.deep_get( + "requestParameters", "userName", default="USERNAME_NOT_FOUND" + ) + return context diff --git a/rules/aws_cloudtrail_rules/aws_iam_create_user.yml b/rules/aws_cloudtrail_rules/aws_iam_create_user.yml new file mode 100644 index 000000000..ca9d7e8ed --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_iam_create_user.yml @@ -0,0 +1,114 @@ +AnalysisType: rule +Filename: aws_iam_create_user.py +RuleID: "AWS.IAM.CreateUser" +DisplayName: "IAM User Created" +Enabled: true +LogTypes: + - AWS.CloudTrail +Reports: + CIS: + - 1.1 + MITRE ATT&CK: + - TA0007:T1078 +Severity: Info +CreateAlert: false +Description: > + An IAM user was created, which could indicate a new user creation or policy update. +Runbook: Check if the user was created by an authorized user. If not, investigate the user creation. +Reference: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html +Tests: + - Name: IAM User Created + ExpectedResult: true + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "CreateUser", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "userName": "new-user" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } + - Name: IAM User Not Created + ExpectedResult: false + Log: + { + "eventVersion": "1.05", + "userIdentity": + { + "type": "AssumedRole", + "principalId": "tester", + "arn": "arn:aws:sts::123456789012:assumed-role/tester", + "accountId": "123456789012", + "accessKeyId": "1", + "sessionContext": + { + "sessionIssuer": + { + "type": "Role", + "principalId": "1111", + "arn": "arn:aws:iam::123456789012:role/tester", + "accountId": "123456789012", + "userName": "Tester", + }, + "webIdFederationData": {}, + "attributes": + { + "mfaAuthenticated": "true", + "creationDate": "2019-01-01T00:00:00Z", + }, + }, + }, + "eventTime": "2019-01-01T00:00:00Z", + "eventSource": "iam.amazonaws.com", + "eventName": "AttachUserPolicy", + "awsRegion": "us-west-2", + "sourceIPAddress": "111.111.111.111", + "userAgent": "console.amazonaws.com", + "requestParameters": + { + "policyArn": "arn:aws:iam::aws:policy/AdministratorAccess", + "userName": "new-user" + }, + "responseElements": null, + "requestID": "1", + "eventID": "1", + "readOnly": false, + "eventType": "AwsApiCall", + "recipientAccountId": "123456789012", + } \ No newline at end of file diff --git a/rules/aws_cloudtrail_rules/aws_iam_user_key_created.py b/rules/aws_cloudtrail_rules/aws_iam_user_key_created.py index 35495aed2..2d3ef073f 100644 --- a/rules/aws_cloudtrail_rules/aws_iam_user_key_created.py +++ b/rules/aws_cloudtrail_rules/aws_iam_user_key_created.py @@ -35,4 +35,7 @@ def alert_context(event): "responseElements", "accessKey", "accessKeyId", default="" ) ) + base["request_username"] = event.deep_get( + "requestParameters", "userName", default="USERNAME_NOT_FOUND" + ) return base diff --git a/rules/aws_cloudtrail_rules/aws_user_login_profile_modified.yml b/rules/aws_cloudtrail_rules/aws_user_login_profile_modified.yml index 39d03388a..71fdc6983 100644 --- a/rules/aws_cloudtrail_rules/aws_user_login_profile_modified.yml +++ b/rules/aws_cloudtrail_rules/aws_user_login_profile_modified.yml @@ -1,6 +1,6 @@ AnalysisType: rule Description: "An attacker with iam:UpdateLoginProfile permission on other users can change the password used to login to the AWS console. May be legitimate account administration." -DisplayName: "AWS User Login Profile Modified" +DisplayName: "DEPRECATED - AWS User Login Profile Modified" Enabled: true Filename: aws_user_login_profile_modified.py Reports: