AWS CloudTrail Attempt To Leave Org


Description

Detects when an actor attempts to remove an AWS account from an Organization. Security configurations are often defined at the organizational level. Leaving the organization can disrupt or totally shut down these controls.

Query · python

from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context
from panther_core import PantherEvent


def rule(event: PantherEvent) -> bool:
    return event.get("eventName") == "LeaveOrganization"


def title(event: PantherEvent) -> str:
    account_name = event.get("recipientAccountId")
    actor = event.udm("actor_user")
    # Return a more informative message if the attempt was unsuccessful
    if not aws_cloudtrail_success(event):
        return f"Failed attempt to remove {account_name} from your AWS organization by {actor}"
    return f"Account {account_name} has been removed from your AWS organization by {actor}"


def severity(event: PantherEvent) -> str:
    # Downgrade to HIGH if attempt is unsuccessful
    if not aws_cloudtrail_success(event):
        return "HIGH"
    return "DEFAULT"


def alert_context(event: PantherEvent) -> dict:
    return aws_rule_context(event)

Analyst notes

Determine if the attempt was successful. Monitor and potentially suspect the user account which attempted the action. Determine if the root account is compromised.

Raw source AWS CloudTrail Attempt To Leave Org · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: aws_cloudtrail_attempt_to_leave_org.py
RuleID: "AWS.CloudTrail.AttemptToLeaveOrg"
DisplayName: AWS CloudTrail Attempt To Leave Org
Enabled: true
LogTypes:
  - AWS.CloudTrail
Severity: Info  
Reports:
  MITRE ATT&CK:
    - TA0005:T1562.008 # Defense Evasion: Impair Defenses - Disable or Modify Cloud Logs
    - TA0005:T1666 # Defense Evasion: Modify Cloud Resource Hierarchy

  Stratus Red Team:
    - aws.defense-evasion.organizations-leave
Description: >
  Detects when an actor attempts to remove an AWS account from an Organization. Security
  configurations are often defined at the organizational level. Leaving the organization can
  disrupt or totally shut down these controls.
Reference: >
  https://stratus-red-team.cloud/attack-techniques/AWS/aws.defense-evasion.organizations-leave/
Runbook: |
  Determine if the attempt was successful. Monitor and potentially suspect the user account which 
  attempted the action. Determine if the root account is compromised.
SummaryAttributes:
  - p_any_ip_addresses
  - p_any_aws_account_ids
Tags:
  - AWS CloudTrail
  - Defense Evasion
  - Impair Defenses
  - Disable or Modify Cloud Logs
  - Modify Cloud Resource Hierarchy
Tests:
  - Name: Failed Attempt to Leave Org
    ExpectedResult: true
    Log:
      {
        "p_event_time": "2025-01-20 15:59:33.000000000",
        "p_log_type": "AWS.CloudTrail",
        "p_parse_time": "2025-01-20 16:05:54.322564138",
        "awsRegion": "us-east-1",
        "errorCode": "AccessDenied",
        "errorMessage": "User: arn:aws:sts::111122223333:assumed-role/SampleRole/SampleSession is not authorized to perform: organizations:LeaveOrganization on resource: * because no identity-based policy allows the organizations:LeaveOrganization action",
        "eventCategory": "Management",
        "eventID": "f52c1358-4ddb-4453-a676-3f4dbc64d713",
        "eventName": "LeaveOrganization",
        "eventSource": "organizations.amazonaws.com",
        "eventTime": "2025-01-20 15:59:33.000000000",
        "eventType": "AwsApiCall",
        "eventVersion": "1.09",
        "managementEvent": true,
        "readOnly": false,
        "recipientAccountId": "111122223333",
        "requestID": "67dce4b9-c7d1-4c91-a686-d34bbd5365eb",
        "sourceIPAddress": "1.2.3.4",
        "tlsDetails": {
          "cipherSuite": "TLS_AES_128_GCM_SHA256",
          "clientProvidedHostHeader": "organizations.us-east-1.amazonaws.com",
          "tlsVersion": "TLSv1.3"
        },
        "userAgent": "example-user-agent",
        "userIdentity": {
          "accessKeyId": "SAMPLE_ACCESS_KEY",
          "accountId": "111122223333",
          "arn": "arn:aws:sts::111122223333:assumed-role/SampleRole/SampleSession",
          "principalId": "SAMPLE_PRINCIPAL_ID:SampleSession",
          "sessionContext": {
            "attributes": {
              "creationDate": "2025-01-20T15:59:30Z",
              "mfaAuthenticated": "false"
            },
            "sessionIssuer": {
              "accountId": "111122223333",
              "arn": "arn:aws:iam::111122223333:role/SampleRole",
              "principalId": "SAMPLE_PRINCIPAL_ID",
              "type": "Role",
              "userName": "SampleRole"
            }
          },
          "type": "AssumedRole"
        }
      }

# ------ paired body: aws_cloudtrail_attempt_to_leave_org.py ------

from panther_aws_helpers import aws_cloudtrail_success, aws_rule_context
from panther_core import PantherEvent


def rule(event: PantherEvent) -> bool:
    return event.get("eventName") == "LeaveOrganization"


def title(event: PantherEvent) -> str:
    account_name = event.get("recipientAccountId")
    actor = event.udm("actor_user")
    # Return a more informative message if the attempt was unsuccessful
    if not aws_cloudtrail_success(event):
        return f"Failed attempt to remove {account_name} from your AWS organization by {actor}"
    return f"Account {account_name} has been removed from your AWS organization by {actor}"


def severity(event: PantherEvent) -> str:
    # Downgrade to HIGH if attempt is unsuccessful
    if not aws_cloudtrail_success(event):
        return "HIGH"
    return "DEFAULT"


def alert_context(event: PantherEvent) -> dict:
    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.