Detection rules › Panther
Unused AWS Region
CloudTrail logged non-read activity from a verboten AWS region.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth | T1535 Unused/Unsupported Cloud Regions |
Rule body yaml
AnalysisType: rule
Filename: aws_unused_region.py
RuleID: "AWS.UnusedRegion"
DisplayName: "Unused AWS Region"
Enabled: false
LogTypes:
- AWS.CloudTrail
Tags:
- AWS
- Defense Evasion:Unused/Unsupported Cloud Regions
- Configuration Required
Reports:
MITRE ATT&CK:
- TA0005:T1535
Severity: High
Description: CloudTrail logged non-read activity from a verboten AWS region.
Runbook: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws-enable-disable-regions.html
Reference: https://attack.mitre.org/techniques/T1535/
SummaryAttributes:
- eventSource
- eventName
- recipientAccountId
- awsRegion
- p_any_aws_arns
Tests:
- Name: Authorized region
ExpectedResult: false
Log:
{
"awsRegion": "us-west-2",
"eventID": "1111",
"eventName": "StartQueryExecution",
"eventSource": "athena.amazonaws.com",
"eventTime": "2021-10-19 04:50:27",
"eventType": "AwsApiCall",
"eventVersion": "1.08",
"managementEvent": true,
"readOnly": false,
"recipientAccountId": "123456789012",
"requestID": "1111",
"requestParameters":
{
"clientRequestToken": "1111",
"queryExecutionContext": { "database": "1111" },
"queryString": "-- Query 2 different time windows for comparison, return sources that have events over the past time window but not within the current time window.\n-- Past time windows: 2 hours\n-- Current time window: 1 hour\n\nWITH PastCount as\n(\nselect p_source_label, count(*) as PastTotal\nfrom panther_views.all_logs \nWHERE p_parse_time >= current_timestamp - interval '7200' second\n and partition_time >= to_unixtime(date_trunc('HOUR', current_timestamp - interval '7200' second))\n group by p_source_label\n),\nCurrentCount as \n(\nselect p_source_label, count(*) as CurrentTotal\nfrom panther_views.all_logs \nWHERE p_parse_time >= current_timestamp - interval '3600' second\n and partition_time >= to_unixtime(date_trunc('HOUR', current_timestamp - interval '3600' second))\n group by p_source_label\n)\nSELECT PastCount.*, coalesce(CurrentCount.CurrentTotal, 0) AS CurrentTotal \nFROM CurrentCount \nRIGHT OUTER JOIN PastCount ON PastCount.p_source_label = CurrentCount.p_source_label\nWHERE CurrentTotal IS NULL",
"resultConfiguration": {},
"workGroup": "Panther",
},
"responseElements":
{ "queryExecutionId": "fc62d701-d474-46a4-b6cf-de6bafdbdb3c" },
"sourceIPAddress": "111.111.111.111",
"userAgent": "aws-sdk-go/1.38.37 (go1.16; linux; amd64) exec-env/AWS_Lambda_go1.x",
"userIdentity":
{
"accessKeyId": "1111",
"accountId": "123456789012",
"arn": "arn:aws:sts::123456789012:assumed-role/example-role/example-user",
"principalId": "1111",
"sessionContext":
{
"attributes":
{
"creationDate": "2021-10-19T04:01:27Z",
"mfaAuthenticated": "false",
},
"sessionIssuer":
{
"accountId": "123456789012",
"arn": "arn:aws:iam::123456789012:role/example-role",
"principalId": "1111",
"type": "Role",
"userName": "example-role",
},
"webIdFederationData": {},
},
"type": "AssumedRole",
},
}
- Name: Unauthorized region, read-only
ExpectedResult: false
Log:
{
"awsRegion": "ap-east-1",
"eventID": "1111",
"eventName": "Decrypt",
"eventSource": "kms.amazonaws.com",
"eventTime": "2021-10-19 00:56:05",
"eventType": "AwsApiCall",
"eventVersion": "1.08",
"managementEvent": true,
"readOnly": true,
"recipientAccountId": "123456789012",
"requestID": "1111",
"requestParameters":
{
"encryptionAlgorithm": "SYMMETRIC_DEFAULT",
"encryptionContext": { "aws:s3:arn": "arn:aws:s3:::1111" },
},
"resources":
[
{
"accountId": "123456789012",
"arn": "arn:aws:kms:us-west-2:123456789012:key/1111",
"type": "AWS::KMS::Key",
},
],
"sourceIPAddress": "AWS Internal",
"userAgent": "AWS Internal",
"userIdentity":
{
"accessKeyId": "1111",
"accountId": "123456789012",
"arn": "arn:aws:sts::123456789012:assumed-role/example-role/example-user",
"principalId": "1111",
"sessionContext":
{
"attributes":
{
"creationDate": "2021-10-19T00:31:41Z",
"mfaAuthenticated": "false",
},
"sessionIssuer":
{
"accountId": "123456789012",
"arn": "arn:aws:iam::123456789012:role/example-role",
"principalId": "1111",
"type": "Role",
"userName": "example-role",
},
"webIdFederationData": {},
},
"type": "AssumedRole",
},
}
- Name: Unauthorized region
ExpectedResult: true
Log:
{
"apiVersion": "20140328",
"awsRegion": "eu-central-1",
"eventID": "1111",
"eventName": "CreateLogStream",
"eventSource": "logs.amazonaws.com",
"eventTime": "2021-10-21 22:29:06",
"eventType": "AwsApiCall",
"eventVersion": "1.08",
"managementEvent": true,
"readOnly": false,
"recipientAccountId": "123456789012",
"requestID": "1111",
"requestParameters":
{
"logGroupName": "/aws/lambda/panther-analysis-api",
"logStreamName": "2021/10/21/[$LATEST]1111",
},
"sourceIPAddress": "111.111.111.111",
"userAgent": "awslambda-worker/1.0 rusoto/0.47.0 rust/1.55.0 linux",
"userIdentity":
{
"accessKeyId": "1111",
"accountId": "123456789012",
"arn": "arn:aws:sts::123456789012:assumed-role/example-role/example-user",
"principalId": "1111",
"sessionContext":
{
"attributes":
{
"creationDate": "2021-10-21T22:29:02Z",
"mfaAuthenticated": "false",
},
"sessionIssuer":
{
"accountId": "123456789012",
"arn": "arn:aws:iam::123456789012:role/example-role",
"principalId": "1111",
"type": "Role",
"userName": "example-role",
},
"webIdFederationData": {},
},
"type": "AssumedRole",
},
}
Detection logic
Condition
awsRegion in ["ap-east-1", "eu-west-3", "eu-central-1"]
readOnly eq "False"
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
eventName | |
eventSource | |
awsRegion | |
recipientAccountId | |
sourceIPAddress | |
userAgent | |
userIdentity | |
userName | userIdentity.sessionContext.sessionIssuer.userName |