Detection rules › Panther

AWS CloudTrail Management Events Enabled

Severity
high
Compliance
CIS 2.1; PCI 10.5.4
Tags
AWS, Security Control, Defense Evasion:Impair Defenses
Reference
https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html
Source
github.com/panther-labs/panther-analysis

This policy ensures that at least one CloudTrail has management (control plane) operations logged.

MITRE ATT&CK coverage

TacticTechniques
StealthT1562 Impair Defenses

Rule body yaml

AnalysisType: policy
Filename: aws_cloudtrail_enabled.py
PolicyID: "AWS.CloudTrail.Enabled"
DisplayName: "AWS CloudTrail Management Events Enabled"
Enabled: true
ResourceTypes:
  - AWS.CloudTrail.Meta
Tags:
  - AWS
  - Security Control
  - Defense Evasion:Impair Defenses
Reports:
  CIS:
    - 2.1
  PCI:
    - 10.5.4
  MITRE ATT&CK:
    - TA0005:T1562
Severity: High
Description: >
  This policy ensures that at least one CloudTrail has
  management (control plane) operations logged.
Runbook: >
  https://docs.runpanther.io/alert-runbooks/built-in-policies/aws-cloudtrail-enabled-in-all-regions
Reference: >
  https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html
Tests:
  - Name: Global CloudTrail Is Enabled
    ExpectedResult: true
    Resource:
      {
        "GlobalEventSelectors":
          [
            {
              "DataResources": null,
              "IncludeManagementEvents": true,
              "ReadWriteType": "All",
            },
            {
              "DataResources":
                [{ "Type": "AWS::S3::Object", "Values": ["arn:aws:s3"] }],
              "IncludeManagementEvents": true,
              "ReadWriteType": "All",
            },
          ],
        "Trails": ["trail1"],
      }
  - Name: CloudTrail Enabled with ReadOnly Management Events
    ExpectedResult: false
    Resource:
      {
        "GlobalEventSelectors":
          [
            {
              "DataResources": null,
              "IncludeManagementEvents": true,
              "ReadWriteType": "Read",
            },
          ],
        "Trails": ["trail1"],
      }
  - Name: No Global CloudTrail Enabled
    ExpectedResult: false
    Resource: { "GlobalEventSelectors": null, "Trails": [] }
  - Name: Advanced Selector With Management
    ExpectedResult: true
    Resource:
      {
        "Trails":
          ["arn:aws:cloudtrail:us-east-1:123456789012:trail/write_to_bucket"],
        "GlobalAdvancedEventSelectors":
          [
            {
              "Name": "Management events selector",
              "FieldSelectors":
                [{ "Field": "eventCategory", "Equals": ["Management"] }],
            },
            {
              "Name": "LambdaDataEvents",
              "FieldSelectors":
                [
                  { "Field": "eventCategory", "Equals": ["Data"] },
                  {
                    "Field": "resources.type",
                    "Equals": ["AWS::Lambda::Function"],
                  },
                ],
            },
            {
              "Name": "S3DataEvents",
              "FieldSelectors":
                [
                  { "Field": "eventCategory", "Equals": ["Data"] },
                  {
                    "Field": "eventName",
                    "NotEquals": ["HeadObject", "UploadPart"],
                  },
                  { "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
                ],
            },
          ],
      }
  - Name: Advanced Selector With Management and readOnly
    ExpectedResult: false
    Resource:
      {
        "Trails":
          ["arn:aws:cloudtrail:us-east-1:123456789012:trail/write_to_bucket"],
        "GlobalAdvancedEventSelectors":
          [
            {
              "Name": "Management events selector",
              "FieldSelectors":
                [
                  { "Field": "eventCategory", "Equals": ["Management"] },
                  { "Field": "readOnly", "Equals": ["true"] },
                ],
            },
            {
              "Name": "LambdaDataEvents",
              "FieldSelectors":
                [
                  { "Field": "eventCategory", "Equals": ["Data"] },
                  {
                    "Field": "resources.type",
                    "Equals": ["AWS::Lambda::Function"],
                  },
                ],
            },
            {
              "Name": "S3DataEvents",
              "FieldSelectors":
                [
                  { "Field": "eventCategory", "Equals": ["Data"] },
                  {
                    "Field": "eventName",
                    "NotEquals": ["HeadObject", "UploadPart"],
                  },
                  { "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
                ],
            },
          ],
      }
  - Name: None Global Selector, Valid Advanced Selector
    ExpectedResult: true
    Resource:
      {
        "AccountId": "123456789012",
        "GlobalEventSelectors": null,
        "GlobalAdvancedEventSelectors":
          [
            {
              "FieldSelectors":
                [
                  {
                    "EndsWith": null,
                    "Equals": ["Data"],
                    "Field": "eventCategory",
                    "NotEndsWith": null,
                    "NotEquals": null,
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                  {
                    "EndsWith": null,
                    "Equals": null,
                    "Field": "eventName",
                    "NotEndsWith": null,
                    "NotEquals": ["UploadPart", "HeadObject"],
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                  {
                    "EndsWith": null,
                    "Equals": ["AWS::S3::Object"],
                    "Field": "resources.type",
                    "NotEndsWith": null,
                    "NotEquals": null,
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                ],
              "Name": "S3DataEvents",
            },
            {
              "FieldSelectors":
                [
                  {
                    "EndsWith": null,
                    "Equals": ["Data"],
                    "Field": "eventCategory",
                    "NotEndsWith": null,
                    "NotEquals": null,
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                  {
                    "EndsWith": null,
                    "Equals": ["AWS::Lambda::Function"],
                    "Field": "resources.type",
                    "NotEndsWith": null,
                    "NotEquals": null,
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                ],
              "Name": "LambdaDataEvents",
            },
            {
              "FieldSelectors":
                [
                  {
                    "EndsWith": null,
                    "Equals": ["Management"],
                    "Field": "eventCategory",
                    "NotEndsWith": null,
                    "NotEquals": null,
                    "NotStartsWith": null,
                    "StartsWith": null,
                  },
                ],
              "Name": "Management events selector",
            },
          ],
        "Name": "AWS.CloudTrail.Meta",
        "Region": "global",
        "ResourceId": "123456789012::AWS.CloudTrail.Meta",
        "ResourceType": "AWS.CloudTrail.Meta",
        "Trails": ["arn:aws:cloudtrail:us-east-1:123456789012/bucket"],
      }

Detection logic

Condition

not (Trails is_not_null and (GlobalEventSelectors is_not_null or GlobalAdvancedEventSelectors is_not_null) and ((GlobalEventSelectors is_not_null and GlobalEventSelectors array_any) or GlobalAdvancedEventSelectors is_not_null))

This rule also runs imperative logic the parser cannot express as a filter; the conditions above are the structured part it could extract.

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
GlobalEventSelectorsarray_any(no value, null check)
GlobalEventSelectorsis_not_null(no value, null check)
GlobalAdvancedEventSelectorsis_not_null(no value, null check)
GlobalAdvancedEventSelectorsis_not_null(no value, null check)
GlobalEventSelectorsis_not_null(no value, null check)
Trailsis_not_null(no value, null check)