Unused AWS Region


Description

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

Query · python

from panther_aws_helpers import aws_rule_context

# Define a list of verboten or unused regions
# Could modify to include expected user mappings: { "123456789012": { "us-west-1", "us-east-2" } }
UNUSED_REGIONS = {"ap-east-1", "eu-west-3", "eu-central-1"}


def rule(event):
    if (
        event.get("awsRegion", "<UNKNOWN_AWS_REGION>") in UNUSED_REGIONS
        and event.get("readOnly") is False
    ):
        return True
    return False


def title(event):
    aws_username = event.deep_get("userIdentity", "sessionContext", "sessionIssuer", "userName")
    return (
        "Non-read-only API call in unused region"
        f" {event.get('awsRegion', '<UNKNOWN_AWS_REGION>')} by user {aws_username}"
    )


def alert_context(event):
    return aws_rule_context(event)

Analyst notes

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws-enable-disable-regions.html

Raw source Unused AWS Region · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
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",
          },
      }


# ------ paired body: aws_unused_region.py ------

from panther_aws_helpers import aws_rule_context

# Define a list of verboten or unused regions
# Could modify to include expected user mappings: { "123456789012": { "us-west-1", "us-east-2" } }
UNUSED_REGIONS = {"ap-east-1", "eu-west-3", "eu-central-1"}


def rule(event):
    if (
        event.get("awsRegion", "<UNKNOWN_AWS_REGION>") in UNUSED_REGIONS
        and event.get("readOnly") is False
    ):
        return True
    return False


def title(event):
    aws_username = event.deep_get("userIdentity", "sessionContext", "sessionIssuer", "userName")
    return (
        "Non-read-only API call in unused region"
        f" {event.get('awsRegion', '<UNKNOWN_AWS_REGION>')} by user {aws_username}"
    )


def alert_context(event):
    return aws_rule_context(event)

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.