Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion plugins/alerts/aws_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func TestAWSRawContracts(t *testing.T) {
cfg, rules, cache := awsConfig(t), awsRules(t), plugins.NewCELCache("aws-raw")
positive := map[string]int{}
negative := map[string]int{}
if len(rules) != 73 {
if len(rules) != 82 {
t.Fatalf("rules: %d", len(rules))
}
for _, f := range awsFixtures(t) {
Expand Down
146 changes: 145 additions & 1 deletion plugins/alerts/testdata/aws_raw.json
Original file line number Diff line number Diff line change
Expand Up @@ -2482,5 +2482,149 @@
"origin.bytesReceived"
],
"matches": []
},
{
"name": "aws-cloudtrail-CreateTrail",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"cloudtrail.amazonaws.com\", \"eventName\": \"CreateTrail\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {}, \"responseElements\": null}",
"expected": {
"action": "CreateTrail",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_cloudtrail_trail_created"
]
},
{
"name": "aws-guardduty-UpdateDetector-disable",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"guardduty.amazonaws.com\", \"eventName\": \"UpdateDetector\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"detectorId\": \"abc\", \"enable\": false}, \"responseElements\": null}",
"expected": {
"action": "UpdateDetector",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_guardduty_detector_updated"
]
},
{
"name": "aws-guardduty-PutFilters",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"guardduty.amazonaws.com\", \"eventName\": \"PutFilters\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"detectorId\": \"abc\", \"filterList\": [{\"name\": \"f\"}]}, \"responseElements\": null}",
"expected": {
"action": "PutFilters",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_guardduty_finding_filter"
]
},
{
"name": "aws-securityhub-DisableSecurityHub",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"securityhub.amazonaws.com\", \"eventName\": \"DisableSecurityHub\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {}, \"responseElements\": null}",
"expected": {
"action": "DisableSecurityHub",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_securityhub_disabled"
]
},
{
"name": "aws-s3-PutBucketLogging-empty",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"s3.amazonaws.com\", \"eventName\": \"PutBucketLogging\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"bucket\": \"b\", \"TargetBucket\": null}, \"responseElements\": null}",
"expected": {
"action": "PutBucketLogging",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_s3_bucket_logging_disabled"
]
},
{
"name": "aws-rds-ModifyDBInstance-deldisable",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"rds.amazonaws.com\", \"eventName\": \"ModifyDBInstance\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"DBInstanceIdentifier\": \"db1\", \"DeletionProtection\": false}, \"responseElements\": null}",
"expected": {
"action": "ModifyDBInstance",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_rds_deletion_protection_or_password_changed"
]
},
{
"name": "aws-kms-ScheduleKeyDeletion",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"kms.amazonaws.com\", \"eventName\": \"ScheduleKeyDeletion\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"KeyId\": \"k1\"}, \"responseElements\": null}",
"expected": {
"action": "ScheduleKeyDeletion",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_kms_key_disabled_or_deletion"
]
},
{
"name": "aws-account-CloseAccount",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"account.amazonaws.com\", \"eventName\": \"CloseAccount\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {}, \"responseElements\": null}",
"expected": {
"action": "CloseAccount",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_account_closed"
]
},
{
"name": "aws-sts-AssumeRoleWithWebIdentity",
"dataSource": "collector-test",
"raw": "{\"eventVersion\": \"1.09\", \"eventTime\": \"2026-09-25T10:00:00Z\", \"eventSource\": \"sts.amazonaws.com\", \"eventName\": \"AssumeRoleWithWebIdentity\", \"eventType\": \"AwsApiCall\", \"awsRegion\": \"us-east-1\", \"sourceIPAddress\": \"198.51.100.20\", \"recipientAccountId\": \"123456789012\", \"userIdentity\": {\"type\": \"IAMUser\", \"accountId\": \"123456789012\", \"arn\": \"arn:aws:iam::123456789012:user/reviewer\", \"principalId\": \"TESTPRINCIPAL\", \"sessionContext\": {\"attributes\": {\"mfaAuthenticated\": \"true\"}}}, \"requestParameters\": {\"RoleArn\": \"arn:aws:iam::123456789012:role/ci\", \"WebIdentityToken\": \"tok\"}, \"responseElements\": null}",
"expected": {
"action": "AssumeRoleWithWebIdentity",
"origin.ip": "198.51.100.20",
"origin.user": "arn:aws:iam::123456789012:user/reviewer",
"actionResult": "success",
"log.awsRecordType": "cloudtrail"
},
"absent": [],
"matches": [
"aws_sts_assume_role_with_web_identity"
]
}
]
]
11 changes: 10 additions & 1 deletion plugins/alerts/testdata/filter-contracts/aws.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,31 @@
"filters/aws/aws.yml"
],
"rules": [
"rules/cloud/aws/aws/aws_account_closed.yml",
"rules/cloud/aws/aws/aws_backup_deletion.yml",
"rules/cloud/aws/aws/aws_cloudtrail_trail_created.yml",
"rules/cloud/aws/aws/aws_config_service_disabled.yml",
"rules/cloud/aws/aws/aws_console_getsignintoken_abuse.yml",
"rules/cloud/aws/aws/aws_ec2_startup_script_modification.yml",
"rules/cloud/aws/aws/aws_ecs_credential_theft.yml",
"rules/cloud/aws/aws/aws_glue_privilege_escalation.yml",
"rules/cloud/aws/aws/aws_golden_saml_attack.yml",
"rules/cloud/aws/aws/aws_guardduty_detector_updated.yml",
"rules/cloud/aws/aws/aws_guardduty_finding_filter.yml",
"rules/cloud/aws/aws/aws_iam_login_profile_modification.yml",
"rules/cloud/aws/aws/aws_kms_key_disabled_or_deletion.yml",
"rules/cloud/aws/aws/aws_kms_key_material_import.yml",
"rules/cloud/aws/aws/aws_rds_deletion_protection_or_password_changed.yml",
"rules/cloud/aws/aws/aws_rds_public_restore.yml",
"rules/cloud/aws/aws/aws_s3_bucket_logging_disabled.yml",
"rules/cloud/aws/aws/aws_s3_versioning_disabled.yml",
"rules/cloud/aws/aws/aws_securityhub_disabled.yml",
"rules/cloud/aws/aws/aws_securityhub_finding_evasion.yml",
"rules/cloud/aws/aws/aws_snapshot_exfiltration.yml",
"rules/cloud/aws/aws/aws_ssm_sendcommand_abuse.yml",
"rules/cloud/aws/aws/aws_sso_idp_change.yml",
"rules/cloud/aws/aws/aws_sso_suspicious_activities.yml",
"rules/cloud/aws/aws/aws_sts_assume_role_with_web_identity.yml",
"rules/cloud/aws/aws/aws_trufflehog_scanning.yml",
"rules/cloud/aws/aws/cloudformation_stack_deletion.yml",
"rules/cloud/aws/aws/cloudtrail_event_selector_manipulation.yml",
Expand Down Expand Up @@ -181,4 +190,4 @@
}
}
]
}
}
25 changes: 25 additions & 0 deletions rules/cloud/aws/aws/aws_account_closed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS Account Closure Requested
impact:
confidentiality: 3
integrity: 3
availability: 3
category: Impact
technique: T1485 - Data Destruction
adversary: origin
description: Identifies a CloseAccount request, the irreversible end-state of account compromise or destructive misuse.
references:
- https://docs.aws.amazon.com/accounts/latest/reference/close-account.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "account.amazonaws.com") &&
equals("log.eventName", "CloseAccount") &&
equals("actionResult","success"))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
25 changes: 25 additions & 0 deletions rules/cloud/aws/aws/aws_cloudtrail_trail_created.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS CloudTrail Trail Created
impact:
confidentiality: 3
integrity: 2
availability: 1
category: Defense Evasion
technique: T1562 - Impair Defenses
adversary: origin
description: Identifies creation of a new CloudTrail trail, which an attacker may use to restrict which events are recorded or to ship logs to an adversary-controlled bucket.
references:
- https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_CreateTrail.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "cloudtrail.amazonaws.com") &&
equals("log.eventName", "CreateTrail") &&
equals("actionResult","success"))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
26 changes: 26 additions & 0 deletions rules/cloud/aws/aws/aws_guardduty_detector_updated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS GuardDuty Detector Updated or Disabled
impact:
confidentiality: 3
integrity: 2
availability: 1
category: Defense Evasion
technique: T1685 - Disable or Modify Cloud Logs
adversary: origin
description: Identifies an UpdateDetector call that disables a GuardDuty detector, stopping threat detection while avoiding a clean DeleteDetector signal.
references:
- https://docs.aws.amazon.com/guardduty/latest/APIReference/API_UpdateDetector.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "guardduty.amazonaws.com") &&
equals("log.eventName", "UpdateDetector") &&
equals("actionResult","success") &&
equals("log.requestParameters.enable",false))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
25 changes: 25 additions & 0 deletions rules/cloud/aws/aws/aws_guardduty_finding_filter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS GuardDuty Finding Filter Added
impact:
confidentiality: 3
integrity: 2
availability: 1
category: Defense Evasion
technique: T1685 - Disable or Modify Cloud Logs
adversary: origin
description: Identifies PutFilters adding a GuardDuty filter that suppresses specific finding types, blinding the account to particular compromise indicators.
references:
- https://docs.aws.amazon.com/guardduty/latest/APIReference/API_PutFilters.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "guardduty.amazonaws.com") &&
equals("log.eventName", "PutFilters") &&
equals("actionResult","success"))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
25 changes: 25 additions & 0 deletions rules/cloud/aws/aws/aws_kms_key_disabled_or_deletion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS KMS Key Disabled or Deletion Scheduled
impact:
confidentiality: 3
integrity: 3
availability: 1
category: Impact
technique: T1486 - Data Encrypted for Impact
adversary: origin
description: Identifies DisableKey or ScheduleKeyDeletion, rendering a customer master key unusable so protected data becomes unreadable, a destructive or ransomware hallmark.
references:
- https://docs.aws.amazon.com/kms/latest/APIReference/API_DisableKey.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "kms.amazonaws.com") &&
oneOf("log.eventName",["DisableKey", "ScheduleKeyDeletion"]) &&
equals("actionResult","success"))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS RDS Deletion Protection Disabled or Master Password Changed
impact:
confidentiality: 3
integrity: 3
availability: 1
category: Impact
technique: T1485 - Data Destruction
adversary: origin
description: Identifies ModifyDBInstance that disables DeletionProtection or changes MasterUserPassword, preparing destructive deletion or seizing database control.
references:
- https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBInstance.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "rds.amazonaws.com") &&
equals("log.eventName", "ModifyDBInstance") &&
equals("actionResult","success") &&
(equals("log.requestParameters.DeletionProtection",false) || exists("log.requestParameters.MasterUserPassword")))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
26 changes: 26 additions & 0 deletions rules/cloud/aws/aws/aws_s3_bucket_logging_disabled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Rule contract revision 2026-09-25; SDK v1.1.36 (gap-fill set).
dataTypes:
- aws
name: AWS S3 Bucket Server Access Logging Disabled
impact:
confidentiality: 3
integrity: 2
availability: 1
category: Defense Evasion
technique: T1562.008 - Disable Cloud Logs
adversary: origin
description: Identifies PutBucketLogging with no target bucket, disabling server-access logging on a bucket and removing the per-object audit trail.
references:
- https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLogging.html
where: |
equals("log.awsRecordType","cloudtrail") &&
(equals("log.eventSource", "s3.amazonaws.com") &&
equals("log.eventName", "PutBucketLogging") &&
equals("actionResult","success") &&
!exists("log.requestParameters.LoggingEnabledTarget.Bucket"))
groupBy:
- lastEvent.dataSource
- lastEvent.log.awsAccountKeyType
- lastEvent.log.awsAccountKey
- adversary.ip
- adversary.user
Loading
Loading