Detection rules › Panther

External Principal Accessing AWS Resources Via VPC Endpoint

Severity
medium
Log types
AWS.CloudTrail
Tags
AWS, CloudTrail, VPCEndpoint, Network Boundary Bridging, Cloud Service Discovery, Exfiltration Over Alternative Protocol
Reference
https://www.wiz.io/blog/aws-vpc-endpoint-cloudtrail
Source
github.com/panther-labs/panther-analysis

This rule detects when a principal from one AWS account accesses resources in a different AWS account using a VPC Endpoint. While cross-account access may be expected in some cases, it could also indicate unauthorized lateral movement between AWS accounts.

MITRE ATT&CK coverage

Rule body yaml

AnalysisType: rule
Filename: aws_vpce_external_principal.py
RuleID: AWS.CloudTrail.VPCE.ExternalPrincipal
DisplayName: External Principal Accessing AWS Resources Via VPC Endpoint
Enabled: true
LogTypes:
  - AWS.CloudTrail
Tags:
  - AWS
  - CloudTrail
  - VPCEndpoint
  - Network Boundary Bridging
  - Cloud Service Discovery
  - Exfiltration Over Alternative Protocol
Reports:
  MITRE ATT&CK:
    - TA0005:T1599 # Network Boundary Bridging
    - TA0007:T1526 # Cloud Service Discovery
    - TA0010:T1048 # Exfiltration Over Alternative Protocol
Severity: Medium
Description: >
  This rule detects when a principal from one AWS account accesses resources in a different AWS account using a VPC Endpoint.
  While cross-account access may be expected in some cases, it could also indicate unauthorized lateral movement between AWS accounts.
Runbook: |
  1. Identify the principal account and the accessed account from the alert context.
  2. Verify if the cross-account access is expected and authorized:
     - Check if the principal account is part of your organization
     - Review IAM policies for the VPC Endpoint to confirm if cross-account access is intentional
     - Check resource policies for the accessed service to confirm if the principal should have access
  3. If the access is unexpected:
     - Review the API calls made by the principal
     - Check the VPC Endpoint configuration for potential misconfiguration
     - Consider restricting VPC Endpoint access to prevent unauthorized cross-account access
     - Investigate for additional signs of unauthorized access
  4. Document findings and take appropriate remediation steps based on investigation.
Reference: https://www.wiz.io/blog/aws-vpc-endpoint-cloudtrail
Tests:
  - Name: External Principal Access
    ExpectedResult: true
    Log:
      {
        "eventVersion": "1.08",
        "eventCategory": "NetworkActivity",
        "eventType": "AwsVpceEvent",
        "eventTime": "2023-03-01T00:00:00Z",
        "awsRegion": "us-east-1",
        "eventSource": "s3.amazonaws.com",
        "eventName": "GetObject",
        "sourceIPAddress": "10.0.0.1",
        "userIdentity": {
          "type": "AWSAccount",
          "accountId": "111111111111",
          "principalId": "AROAEXAMPLE:session-name"
        },
        "recipientAccountId": "222222222222",
        "requestParameters": {
          "bucketName": "example-bucket",
          "key": "sensitive-file.txt"
        },
        "responseElements": null,
        "vpcEndpointId": "vpce-EXAMPLE08c1b6b9b7",
        "vpcEndpointAccountId": "222222222222"
      }

  - Name: Same Account Access
    ExpectedResult: false
    Log:
      {
        "eventVersion": "1.08",
        "eventCategory": "NetworkActivity",
        "eventType": "AwsVpceEvent",
        "eventTime": "2023-03-01T00:00:00Z",
        "awsRegion": "us-east-1",
        "eventSource": "s3.amazonaws.com",
        "eventName": "GetObject",
        "sourceIPAddress": "10.0.0.1",
        "userIdentity": {
          "type": "AWSAccount",
          "accountId": "222222222222",
          "principalId": "AROAEXAMPLE:session-name"
        },
        "recipientAccountId": "222222222222",
        "requestParameters": {
          "bucketName": "example-bucket",
          "key": "sensitive-file.txt"
        },
        "responseElements": null,
        "vpcEndpointId": "vpce-EXAMPLE08c1b6b9b7",
        "vpcEndpointAccountId": "222222222222"
      }

  - Name: Non-VPC Event
    ExpectedResult: false
    Log:
      {
        "eventVersion": "1.08",
        "eventCategory": "Management",
        "eventType": "AwsApiCall",
        "eventTime": "2023-03-01T00:00:00Z",
        "awsRegion": "us-east-1",
        "eventSource": "s3.amazonaws.com",
        "eventName": "GetObject",
        "sourceIPAddress": "10.0.0.1",
        "userIdentity": {
          "type": "AWSAccount",
          "accountId": "111111111111",
          "principalId": "AROAEXAMPLE:session-name"
        },
        "recipientAccountId": "222222222222",
        "requestParameters": {
          "bucketName": "example-bucket",
          "key": "sensitive-file.txt"
        },
        "responseElements": null
      } 

Detection logic

Condition

not (eventType ne "AwsVpceEvent" or eventCategory ne "NetworkActivity")
userIdentity.type eq "AWSAccount"
userIdentity not contains "arn"
userIdentity contains "principalId"
recipientAccountId is_not_null
userIdentity.accountId is_not_null
recipientAccountId cross_field_compare "userIdentity.accountId"

Exclusions

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

FieldKindExcluded values
eventCategoryneNetworkActivity
eventTypeneAwsVpceEvent
userIdentitycontainsarn

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
recipientAccountIdcross_field_compare
  • userIdentity.accountId transforms: op:ne
recipientAccountIdis_not_null
  • (no value, null check)
userIdentitycontains
  • principalId
userIdentity.accountIdis_not_null
  • (no value, null check)
userIdentity.typeeq
  • AWSAccount

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
actor_user
accountIduserIdentity.accountId