diff --git a/packs/aws.yml b/packs/aws.yml index 865d1eaf2..62bfae245 100644 --- a/packs/aws.yml +++ b/packs/aws.yml @@ -7,130 +7,132 @@ PackDefinition: # Data Exposure - AWS.AMI.Private - AWS.CloudTrail.AMIModifiedForPublicAccess + - AWS.CloudTrail.ResourceMadePublic - AWS.CloudTrail.S3Bucket.Public + - AWS.CloudTrail.SnapshotMadePublic + - AWS.EC2.Instance.DetailedMonitoring + - AWS.EC2.Traffic.Mirroring - AWS.IAM.AccessKeyCompromised - - AWS.KMS.RestrictsUsage - AWS.KMS.CustomerManagedKeyLoss + - AWS.KMS.RestrictsUsage + - AWS.Macie.Evasion - AWS.RDS.Instance.PublicAccess - AWS.RDS.Instance.SnapshotPublicAccess - - AWS.S3.Bucket.PublicRead - - AWS.S3.Bucket.PublicWrite - AWS.S3.Bucket.PolicyAllowWithNotPrincipal - AWS.S3.Bucket.PrincipalRestrictions - AWS.S3.Bucket.PublicAccessBlock + - AWS.S3.Bucket.PublicRead + - AWS.S3.Bucket.PublicWrite - AWS.S3.Bucket.SecureAccess - AWS.S3.Bucket.Versioning - - AWS.EC2.Traffic.Mirroring - - AWS.Macie.Evasion - - AWS.CloudTrail.ResourceMadePublic - - AWS.CloudTrail.SnapshotMadePublic - - AWS.EC2.Instance.DetailedMonitoring # Encryption Status + - AWS.EC2.EBS.Encryption.Disabled - AWS.EC2.Volume.Encryption - AWS.EC2.Volume.Snapshot.Encrypted - - AWS.EC2.EBS.Encryption.Disabled - - AWS.Redshift.Cluster.Encryption - AWS.RDS.Instance.Encryption + - AWS.Redshift.Cluster.Encryption - AWS.S3.Bucket.Encryption # Networking Policies - - AWS.NetworkACL.RestrictsInboundTraffic - - AWS.SecurityGroup.AdministrativeIngress - - AWS.SecurityGroup.OnlyDMZPubliclyAccessible - - AWS.SecurityGroup.RestrictsInboundTraffic + - AWS.CloudTrail.NetworkACLPermissiveEntry + - AWS.DNS.Crypto.Domain - AWS.EC2.GatewayModified - AWS.EC2.Monitoring - AWS.EC2.NetworkACLModified - AWS.EC2.RouteTableModified - AWS.EC2.VPCModified - AWS.IPSet.Modified - - AWS.CloudTrail.NetworkACLPermissiveEntry - - AWS.DNS.Crypto.Domain + - AWS.NetworkACL.RestrictsInboundTraffic + - AWS.SecurityGroup.AdministrativeIngress + - AWS.SecurityGroup.OnlyDMZPubliclyAccessible + - AWS.SecurityGroup.RestrictsInboundTraffic - AWS.VPC.HealthyLogStatus # Root Activity + - AWS.CloudTrail.RootAccessKeyCreated + - AWS.CloudTrail.RootPasswordChanged - AWS.Console.RootLogin - AWS.Console.RootLoginFailed + - AWS.EC2.Instance.DetailedMonitoring - AWS.Root.Activity - - AWS.CloudTrail.RootAccessKeyCreated - - AWS.CloudTrail.RootPasswordChanged - AWS.RootAccount.AccessKeys - AWS.RootAccount.MFA - - AWS.EC2.Instance.DetailedMonitoring # User and Account Policies and Rules + - AWS.CloudTrail.IAMAnythingChanged + - AWS.CloudTrail.IAMCompromisedKeyQuarantine + - AWS.CloudTrail.Password.Policy.Discovery - AWS.Console.LoginWithoutMFA - AWS.Console.LoginWithoutSAML - - AWS.PasswordPolicy.PasswordReuse - - AWS.Suspicious.SAML.Activity + - AWS.EC2.SecurityGroupModified + - AWS.IAM.Backdoor.User.Keys + - AWS.IAM.CredentialsUpdated - AWS.IAM.Entity.InlinePolicyDoesNotGrantNetworkAdminAccess + - AWS.IAM.Group.Users + - AWS.IAM.Policy.AssignedToUser + - AWS.IAM.PolicyModified - AWS.IAM.User.MFA + - AWS.IAMUser.ReconAccessDenied - AWS.Password.Unused - AWS.PasswordPolicy.ComplexityGuidelines - AWS.PasswordPolicy.PasswordAgeLimit - - AWS.EC2.SecurityGroupModified - - AWS.CloudTrail.IAMAnythingChanged - - AWS.IAM.PolicyModified - - AWS.IAM.Backdoor.User.Keys - - AWS.IAMUser.ReconAccessDenied - - AWS.IAM.CredentialsUpdated + - AWS.PasswordPolicy.PasswordReuse + - AWS.Suspicious.SAML.Activity - AWS.User.Login.Profile.Modified - - AWS.CloudTrail.Password.Policy.Discovery - - AWS.IAM.Group.Users - - AWS.IAM.Policy.AssignedToUser - - AWS.CloudTrail.IAMCompromisedKeyQuarantine # General Policies and Rules - - AWS.ACM.Certificate.Valid + - Amazon.EKS.Audit.Multiple403 + - Amazon.EKS.Audit.SystemNamespaceFromPublicIP + - AWS.AccessKey.Rotation + - AWS.AccessKey.Unused + - AWS.AccessKeys.AccountCreation - AWS.ACM.Certificate.Expiration + - AWS.ACM.Certificate.Valid + - AWS.CloudFormation.Stack.Drifted + - AWS.CloudFormation.Stack.TerminationProtection + - AWS.CloudFormation.Stack.UsesIAMServiceRole + - AWS.CloudTrail.CodebuildProjectMadePublic - AWS.CloudTrail.Created - AWS.CloudTrail.Enabled + - AWS.CloudTrail.SecurityConfigurationChange - AWS.CloudTrail.Stopped - - AWS.CloudTrail.CodebuildProjectMadePublic - - AWS.ConfigService.Created - - AWS.ConfigService.DisabledDeleted + - AWS.CloudTrail.UnauthorizedAPICall + - AWS.CloudWatchLogs.DataRetention1Year + - AWS.CloudWatchLogs.Encrypted + - AWS.Config.GlobalResources + - AWS.Config.RecordAllResourceTypes - AWS.Config.RecordingEnabled - AWS.Config.RecordingNoErrors - - AWS.IAM.Policy.AdministrativePrivileges + - AWS.ConfigService.Created + - AWS.ConfigService.DisabledDeleted + - AWS.DynamoDB.Autoscaling + - AWS.EC2.Instance.EBSOptimization + - AWS.EC2.Startup.Script.Change + - AWS.ELBV2.LoadBalancer.HasSSLPolicy + - AWS.ELBv2.SSLPolicy - AWS.GuardDuty.Enabled - AWS.GuardDuty.HighSeverityFinding - - AWS.GuardDuty.MediumSeverityFinding - AWS.GuardDuty.LowSeverityFinding - - AWS.ELBV2.LoadBalancer.HasSSLPolicy - - AWS.ELBv2.SSLPolicy - - AWS.WAF.HasXSSPredicate - - AWS.WAF.Disassociation - - AWS.EC2.Startup.Script.Change - - AWS.EC2.Instance.EBSOptimization + - AWS.GuardDuty.MediumSeverityFinding + - AWS.IAM.Policy.AdministrativePrivileges + - AWS.RDS.InstanceHighAvailability + - AWS.RDS.ManualSnapshotCreated - AWS.RDS.MasterPasswordUpdated - AWS.RDS.PublicRestore - - AWS.RDS.InstanceHighAvailability - - AWS.S3.GreyNoiseActivity - - AWS.S3.BucketDeleted - - AWS.S3.BucketPolicyModified + - AWS.RDS.SnapshotShared + - AWS.Redshift.Cluster.Logging + - AWS.Redshift.Cluster.SnapshotRetention + - AWS.Redshift.Cluster.VersionUpgrade - AWS.S3.Bucket.ActionRestrictions - - AWS.S3.ServerAccess.Error - - AWS.S3.ServerAccess.Insecure - AWS.S3.Bucket.LifecycleConfiguration - AWS.S3.Bucket.Logging - AWS.S3.Bucket.MFADelete - AWS.S3.Bucket.NameDNSCompliance - - AWS.CloudTrail.SecurityConfigurationChange + - AWS.S3.BucketDeleted + - AWS.S3.BucketPolicyModified + - AWS.S3.GreyNoiseActivity + - AWS.S3.ServerAccess.Error + - AWS.S3.ServerAccess.Insecure - AWS.SecurityHub.Finding.Evasion - - AWS.CloudTrail.UnauthorizedAPICall - - Amazon.EKS.Audit.Multiple403 - - Amazon.EKS.Audit.SystemNamespaceFromPublicIP - - AWS.CloudFormation.Stack.Drifted - - AWS.CloudFormation.Stack.UsesIAMServiceRole - - AWS.CloudFormation.Stack.TerminationProtection - - AWS.CloudWatchLogs.DataRetention1Year - - AWS.CloudWatchLogs.Encrypted - - AWS.Config.RecordAllResourceTypes - - AWS.Config.GlobalResources - - AWS.DynamoDB.Autoscaling - - AWS.AccessKey.Rotation - - AWS.AccessKey.Unused - - AWS.AccessKeys.AccountCreation - - AWS.Redshift.Cluster.Logging - - AWS.Redshift.Cluster.SnapshotRetention - - AWS.Redshift.Cluster.VersionUpgrade - AWS.VPC.FlowLogs + - AWS.WAF.Disassociation + - AWS.WAF.HasXSSPredicate # AWS DataModels - Standard.AWS.ALB - Standard.AWS.CloudTrail diff --git a/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.py b/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.py index 819a87e49..8204d6d6f 100644 --- a/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.py +++ b/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.py @@ -12,7 +12,7 @@ def rule(event): ) for item in added_perms: - if item.get("group") == "all": + if item.get("userId") or item.get("group") == "all": return True return False diff --git a/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.yml b/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.yml index 1f076391f..8e54d3c77 100644 --- a/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.yml +++ b/rules/aws_cloudtrail_rules/aws_ami_modified_for_public_access.yml @@ -190,7 +190,7 @@ Tests: } - Name: AMI Added to User - ExpectedResult: false + ExpectedResult: true Log: { "awsRegion": "us-west-2", diff --git a/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.py b/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.py new file mode 100644 index 000000000..4261f41f3 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.py @@ -0,0 +1,21 @@ +from panther_base_helpers import aws_rule_context + + +def rule(event): + return all( + [ + event.get("eventSource", "") == "rds.amazonaws.com", + event.get("eventName", "") == "CreateDBSnapshot", + event.deep_get("responseElements", "snapshotType") in {"manual", "public"}, + ] + ) + + +def title(event): + account_id = event.get("recipientAccountId", "") + rds_instance_id = event.deep_get("responseElements", "dBInstanceIdentifier") + return f"Manual RDS Snapshot Created in [{account_id}] for RDS instance [{rds_instance_id}]" + + +def alert_context(event): + return aws_rule_context(event) diff --git a/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.yml b/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.yml new file mode 100644 index 000000000..54fb358aa --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_rds_manual_snapshot_created.yml @@ -0,0 +1,331 @@ +AnalysisType: rule +Filename: aws_rds_manual_snapshot_created.py +RuleID: "AWS.RDS.ManualSnapshotCreated" +DisplayName: "AWS RDS Manual/Public Snapshot Created" +Enabled: false +LogTypes: + - AWS.CloudTrail +Tags: + - AWS + - Exfiltration + - Transfer Data to Cloud Account +Reports: + MITRE ATT&CK: + - TA0010:T1537 +Severity: Low +Description: > + A manual snapshot of an RDS database was created. + An attacker may use this to exfiltrate the DB contents to another account; use this as a correlation rule. +Runbook: > + Ensure the snapshot was shared with an allowed AWS account. If not, delete the snapshot and quarantine the compromised IAM user. +Reference: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateSnapshot.html +SummaryAttributes: + - eventSource + - recipientAccountId + - awsRegion + - p_any_aws_arns +Tests: + - + Name: Manual Snapshot Created + ExpectedResult: true + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/ARole/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/ARole", + "accountId": "123456789012", + "userName": "ARole" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-08T13:53:48Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-08T14:55:19Z", + "eventSource": "rds.amazonaws.com", + "eventName": "CreateDBSnapshot", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.1.2 (+https://www.terraform.io) terraform-provider-aws/3.76.1 (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go/1.44.157 (go1.19.3; darwin; arm64) 68319f60-9dec-43b2-9702-de3a08c9d8a3 HashiCorp-terraform-exec/0.17.3", + "requestParameters": { + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "dBSnapshotIdentifier": "exfiltration" + }, + "responseElements": { + "allocatedStorage": 10, + "instanceCreateTime": "Dec 8, 2023 2:55:17 PM", + "dBSnapshotIdentifier": "exfiltration", + "dbiResourceId": "db-TYZSSMTWIABIR6QKKFGI55XKJQ", + "port": 3306, + "availabilityZone": "us-west-2b", + "dBSnapshotArn": "arn:aws:rds:us-west-2:123456789012:snapshot:exfiltration", + "processorFeatures": [], + "encrypted": false, + "percentProgress": 0, + "optionGroupName": "default:mysql-8-0", + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "storageType": "gp2", + "iAMDatabaseAuthenticationEnabled": false, + "vpcId": "vpc-0c9c141888d129377", + "storageThroughput": 0, + "dedicatedLogVolume": false, + "status": "creating", + "masterUsername": "admin", + "engine": "mysql", + "snapshotType": "manual", + "engineVersion": "8.0.33", + "licenseModel": "general-public-license", + "snapshotTarget": "region" + }, + "requestID": "e5fd8d41-db7c-45df-a21a-f9cff8c19755", + "eventID": "c665b42c-89b4-4072-ad71-0f9c8d50f649", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } + - + Name: Public Snapshot Created + ExpectedResult: true + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/ARole/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/ARole", + "accountId": "123456789012", + "userName": "ARole" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-08T13:53:48Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-08T14:55:19Z", + "eventSource": "rds.amazonaws.com", + "eventName": "CreateDBSnapshot", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.1.2 (+https://www.terraform.io) terraform-provider-aws/3.76.1 (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go/1.44.157 (go1.19.3; darwin; arm64) 68319f60-9dec-43b2-9702-de3a08c9d8a3 HashiCorp-terraform-exec/0.17.3", + "requestParameters": { + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "dBSnapshotIdentifier": "exfiltration" + }, + "responseElements": { + "allocatedStorage": 10, + "instanceCreateTime": "Dec 8, 2023 2:55:17 PM", + "dBSnapshotIdentifier": "exfiltration", + "dbiResourceId": "db-TYZSSMTWIABIR6QKKFGI55XKJQ", + "port": 3306, + "availabilityZone": "us-west-2b", + "dBSnapshotArn": "arn:aws:rds:us-west-2:123456789012:snapshot:exfiltration", + "processorFeatures": [], + "encrypted": false, + "percentProgress": 0, + "optionGroupName": "default:mysql-8-0", + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "storageType": "gp2", + "iAMDatabaseAuthenticationEnabled": false, + "vpcId": "vpc-0c9c141888d129377", + "storageThroughput": 0, + "dedicatedLogVolume": false, + "status": "creating", + "masterUsername": "admin", + "engine": "mysql", + "snapshotType": "public", + "engineVersion": "8.0.33", + "licenseModel": "general-public-license", + "snapshotTarget": "region" + }, + "requestID": "e5fd8d41-db7c-45df-a21a-f9cff8c19755", + "eventID": "c665b42c-89b4-4072-ad71-0f9c8d50f649", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } + - + Name: Automated Snapshot Created + ExpectedResult: false + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/ARole/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/ARole", + "accountId": "123456789012", + "userName": "ARole" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-08T13:53:48Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-08T14:55:19Z", + "eventSource": "rds.amazonaws.com", + "eventName": "CreateDBSnapshot", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.1.2 (+https://www.terraform.io) terraform-provider-aws/3.76.1 (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go/1.44.157 (go1.19.3; darwin; arm64) 68319f60-9dec-43b2-9702-de3a08c9d8a3 HashiCorp-terraform-exec/0.17.3", + "requestParameters": { + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "dBSnapshotIdentifier": "exfiltration" + }, + "responseElements": { + "allocatedStorage": 10, + "instanceCreateTime": "Dec 8, 2023 2:55:17 PM", + "dBSnapshotIdentifier": "exfiltration", + "dbiResourceId": "db-TYZSSMTWIABIR6QKKFGI55XKJQ", + "port": 3306, + "availabilityZone": "us-west-2b", + "dBSnapshotArn": "arn:aws:rds:us-west-2:123456789012:snapshot:exfiltration", + "processorFeatures": [], + "encrypted": false, + "percentProgress": 0, + "optionGroupName": "default:mysql-8-0", + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "storageType": "gp2", + "iAMDatabaseAuthenticationEnabled": false, + "vpcId": "vpc-0c9c141888d129377", + "storageThroughput": 0, + "dedicatedLogVolume": false, + "status": "creating", + "masterUsername": "admin", + "engine": "mysql", + "snapshotType": "automated", + "engineVersion": "8.0.33", + "licenseModel": "general-public-license", + "snapshotTarget": "region" + }, + "requestID": "e5fd8d41-db7c-45df-a21a-f9cff8c19755", + "eventID": "c665b42c-89b4-4072-ad71-0f9c8d50f649", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } + - + Name: Awsbackup Snapshot Created + ExpectedResult: false + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/ARole/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/ARole", + "accountId": "123456789012", + "userName": "ARole" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-08T13:53:48Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-08T14:55:19Z", + "eventSource": "rds.amazonaws.com", + "eventName": "CreateDBSnapshot", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "APN/1.0 HashiCorp/1.0 Terraform/1.1.2 (+https://www.terraform.io) terraform-provider-aws/3.76.1 (+https://registry.terraform.io/providers/hashicorp/aws) aws-sdk-go/1.44.157 (go1.19.3; darwin; arm64) 68319f60-9dec-43b2-9702-de3a08c9d8a3 HashiCorp-terraform-exec/0.17.3", + "requestParameters": { + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "dBSnapshotIdentifier": "exfiltration" + }, + "responseElements": { + "allocatedStorage": 10, + "instanceCreateTime": "Dec 8, 2023 2:55:17 PM", + "dBSnapshotIdentifier": "exfiltration", + "dbiResourceId": "db-TYZSSMTWIABIR6QKKFGI55XKJQ", + "port": 3306, + "availabilityZone": "us-west-2b", + "dBSnapshotArn": "arn:aws:rds:us-west-2:123456789012:snapshot:exfiltration", + "processorFeatures": [], + "encrypted": false, + "percentProgress": 0, + "optionGroupName": "default:mysql-8-0", + "dBInstanceIdentifier": "terraform-20231208145149286600000001", + "storageType": "gp2", + "iAMDatabaseAuthenticationEnabled": false, + "vpcId": "vpc-0c9c141888d129377", + "storageThroughput": 0, + "dedicatedLogVolume": false, + "status": "creating", + "masterUsername": "admin", + "engine": "mysql", + "snapshotType": "awsbackup", + "engineVersion": "8.0.33", + "licenseModel": "general-public-license", + "snapshotTarget": "region" + }, + "requestID": "e5fd8d41-db7c-45df-a21a-f9cff8c19755", + "eventID": "c665b42c-89b4-4072-ad71-0f9c8d50f649", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } diff --git a/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.py b/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.py new file mode 100644 index 000000000..3729e2e95 --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.py @@ -0,0 +1,32 @@ +from panther_base_helpers import aws_rule_context + + +def rule(event): + if all( + [ + event.get("eventSource", "") == "rds.amazonaws.com", + event.get("eventName", "") == "ModifyDBSnapshotAttribute" + or event.get("eventName", "") == "ModifyDBClusterSnapshotAttribute", + event.deep_get("requestParameters", "attributeName") == "restore", + ] + ): + current_account_id = event.deep_get("userIdentity", "accountId", default="") + shared_account_ids = event.deep_get("requestParameters", "valuesToAdd", default=[]) + if shared_account_ids: + return any( + account_id for account_id in shared_account_ids if account_id != current_account_id + ) + return False + return False + + +def title(event): + account_id = event.get("recipientAccountId", default="") + rds_instance_id = event.deep_get( + "responseElements", "dBInstanceIdentifier", default="" + ) + return f"RDS Snapshot Shared in [{account_id}] for RDS instance [{rds_instance_id}]" + + +def alert_context(event): + return aws_rule_context(event) diff --git a/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.yml b/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.yml new file mode 100644 index 000000000..eb77d4b8b --- /dev/null +++ b/rules/aws_cloudtrail_rules/aws_rds_snapshot_shared.yml @@ -0,0 +1,150 @@ +AnalysisType: rule +Filename: aws_rds_snapshot_shared.py +RuleID: "AWS.RDS.SnapshotShared" +DisplayName: "AWS RDS Snapshot Shared" +Enabled: true +LogTypes: + - AWS.CloudTrail +Tags: + - AWS + - Exfiltration + - Transfer Data to Cloud Account +Severity: High +Reports: + MITRE ATT&CK: + - TA0010:T1537 +Description: > + An RDS snapshot was shared with another account. This could be an indicator of exfiltration. +Runbook: > + Ensure that the snapshot was shared intentionally and with an approved account. If not, remove the snapshot and quarantine the compromised IAM user. +Reference: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ShareSnapshot.html +SummaryAttributes: + - eventSource + - recipientAccountId + - awsRegion + - p_any_aws_arns +Tests: + - + Name: Snapshot shared with another account + ExpectedResult: true + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_DevAdmin_635426549a280cc6/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/AWSReservedSSO_DevAdmin_635426549a280cc6", + "accountId": "123456789012", + "userName": "AWSReservedSSO_DevAdmin_635426549a280cc6" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-12T19:43:57Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-12T20:12:22Z", + "eventSource": "rds.amazonaws.com", + "eventName": "ModifyDBSnapshotAttribute", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "68319f60-9dec-43b2-9702-de3a08c9d8a3", + "requestParameters": { + "dBSnapshotIdentifier": "exfiltration", + "attributeName": "restore", + "valuesToAdd": [ + "193672423079" + ] + }, + "responseElements": { + "dBSnapshotIdentifier": "exfiltration", + "dBSnapshotAttributes": [ + { + "attributeName": "restore", + "attributeValues": [ + "193672423079" + ] + } + ] + }, + "requestID": "b7f91314-eb8b-4be5-995d-6b97d70dfb3b", + "eventID": "86581591-0f39-4eae-9a8d-b2224a3c91fa", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } + - + Name: Snapshot shared with no accounts + ExpectedResult: false + Log: + { + "eventVersion": "1.08", + "userIdentity": { + "type": "AssumedRole", + "principalId": "AROA2DFDF0C1FDFCAD2B2:fake.user", + "arn": "arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_DevAdmin_635426549a280cc6/fake.user", + "accountId": "123456789012", + "accessKeyId": "ASIAFFA5AFEC02FFCD8ED", + "sessionContext": { + "sessionIssuer": { + "type": "Role", + "principalId": "AROA2DFDF0C1FDFCAD2B2", + "arn": "arn:aws:iam::123456789012:role/aws-reserved/sso.amazonaws.com/us-west-2/AWSReservedSSO_DevAdmin_635426549a280cc6", + "accountId": "123456789012", + "userName": "AWSReservedSSO_DevAdmin_635426549a280cc6" + }, + "webIdFederationData": {}, + "attributes": { + "creationDate": "2023-12-12T19:43:57Z", + "mfaAuthenticated": "false" + } + } + }, + "eventTime": "2023-12-12T20:12:22Z", + "eventSource": "rds.amazonaws.com", + "eventName": "ModifyDBSnapshotAttribute", + "awsRegion": "us-west-2", + "sourceIPAddress": "1.2.3.4", + "userAgent": "68319f60-9dec-43b2-9702-de3a08c9d8a3", + "requestParameters": { + "dBSnapshotIdentifier": "exfiltration", + "attributeName": "restore", + "valuesToAdd": [] + }, + "responseElements": { + "dBSnapshotIdentifier": "exfiltration", + "dBSnapshotAttributes": [ + { + "attributeName": "restore", + "attributeValues": [] + } + ] + }, + "requestID": "b7f91314-eb8b-4be5-995d-6b97d70dfb3b", + "eventID": "86581591-0f39-4eae-9a8d-b2224a3c91fa", + "readOnly": false, + "eventType": "AwsApiCall", + "managementEvent": true, + "recipientAccountId": "123456789012", + "eventCategory": "Management", + "tlsDetails": { + "tlsVersion": "TLSv1.3", + "cipherSuite": "TLS_AES_128_GCM_SHA256", + "clientProvidedHostHeader": "rds.us-west-2.amazonaws.com" + } + } diff --git a/rules/aws_cloudtrail_rules/aws_snapshot_made_public.py b/rules/aws_cloudtrail_rules/aws_snapshot_made_public.py index 78304036a..caee2aa97 100644 --- a/rules/aws_cloudtrail_rules/aws_snapshot_made_public.py +++ b/rules/aws_cloudtrail_rules/aws_snapshot_made_public.py @@ -18,14 +18,10 @@ def rule(event): for item in items: if not isinstance(item, (Mapping, dict)): continue - if item.get("group") == "all": + if item.get("userId") or item.get("group") == "all": return True return False - # RDS snapshot made public - if event.get("eventName") == "ModifyDBClusterSnapshotAttribute": - return "all" in deep_get(event, "requestParameters", "valuesToAdd", default=[]) - return False