Detection rules › Panther

Unused AWS Region

Severity
high
Log types
AWS.CloudTrail
Tags
AWS, Defense Evasion:Unused/Unsupported Cloud Regions, Configuration Required
Reference
https://attack.mitre.org/techniques/T1535/
Source
github.com/panther-labs/panther-analysis

CloudTrail logged non-read activity from a verboten AWS region.

MITRE ATT&CK coverage

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.

FieldKindValues
awsRegionin
  • ap-east-1
  • eu-central-1
  • eu-west-3
readOnlyeq
  • False

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.

FieldSource
eventName
eventSource
awsRegion
recipientAccountId
sourceIPAddress
userAgent
userIdentity
userNameuserIdentity.sessionContext.sessionIssuer.userName