aws-lf-get-data-access-exfil

A principal who can read LF-governed table data (via Athena/Glue/EMR/Redshift Spectrum) and can write query output to an external S3 destination (UNLOAD / Glue job target / EMR write) can exfiltrate the governed data out of the account's LF-controlled boundary.

derived aws emits CanExfiltrate

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanReadData {'table': None}

where

node_type(?table) == DataWarehouse ?table.provider_type in ['AWS::Glue::Table', 'AWS::Glue::Database'] ?principal can direct query output to an external S3 destination: (a) Athena UNLOAD to s3://<external-bucket>: principal has s3:PutObject on the external bucket AND athena:StartQueryExecution is ACTIVE (from rule 3) OR (b) Glue ETL job writes to external S3: the Glue job's service role has s3:PutObject on the external bucket AND ?principal CanModifyCode or CanTrigger the Glue job (Glue adapter handles this; here the external-write path is confirmed) OR (c) EMR step writes to external S3: similar to Glue

emit

source typeIdentity
target typeDataWarehouse
source?principal
target?table
permissionsathena:StartQueryExecution s3:PutObject (on destination bucket) lakeformation:GetDataAccess
conditionsiam_permission resource_policy
state logicACTIVE when CanReadData on ?table is ACTIVE (rule 3) AND the principal can direct output to an external S3 destination (s3:PutObject confirmed on the external bucket or the analytics job's execution role is confirmed to write externally). CONDITIONAL(iam_permission) when the s3:PutObject on the external destination is unconfirmed. CONDITIONAL(resource_policy) when the external bucket's policy may block writes from the analytics service's role. Inherit weakest from the contributing CanReadData edge; a CONDITIONAL CanReadData (e.g., analytics-service IAM unconfirmed) yields at best CONDITIONAL here. BLOCKED if the analytics service blocks UNLOAD to external buckets (Athena workgroup EnforceWorkgroupConfiguration with OutputLocation constraint) or an SCP restricts cross-account s3:PutObject.

Narrative

{principal.name} can read LF-governed table {table.name} (via Athena / Glue / EMR) and can direct query output to an external S3 destination (UNLOAD to s3://<attacker-bucket> or Glue/EMR job writing externally). This enables exfiltrating the governed table's data out of the account's LF-controlled boundary.

Raw rule rules/derived/aws/lakeformation.yaml

id: aws-lf-get-data-access-exfil
emits: CanExfiltrate
description: A principal who can read LF-governed table data (via Athena/Glue/EMR/Redshift Spectrum) and
  can write query output to an external S3 destination (UNLOAD / Glue job target / EMR write) can exfiltrate
  the governed data out of the account's LF-controlled boundary.
match:
- - principal: null
  - CanReadData
  - table: null
where:
- node_type(?table) == DataWarehouse
- ?table.provider_type in ['AWS::Glue::Table', 'AWS::Glue::Database']
- "?principal can direct query output to an external S3 destination: (a) Athena UNLOAD to s3://<external-bucket>:\
  \ principal has s3:PutObject on\n    the external bucket AND athena:StartQueryExecution is ACTIVE (from\
  \ rule 3)\nOR (b) Glue ETL job writes to external S3: the Glue job's service role has\n    s3:PutObject\
  \ on the external bucket AND ?principal CanModifyCode or CanTrigger\n    the Glue job (Glue adapter\
  \ handles this; here the external-write path is confirmed)\nOR (c) EMR step writes to external S3: similar\
  \ to Glue"
emit:
  source_type: Identity
  target_type: DataWarehouse
  source: ?principal
  target: ?table
  permissions:
  - athena:StartQueryExecution
  - s3:PutObject (on destination bucket)
  - lakeformation:GetDataAccess
  conditions:
  - iam_permission
  - resource_policy
  state_logic: ACTIVE when CanReadData on ?table is ACTIVE (rule 3) AND the principal can direct output
    to an external S3 destination (s3:PutObject confirmed on the external bucket or the analytics job's
    execution role is confirmed to write externally). CONDITIONAL(iam_permission) when the s3:PutObject
    on the external destination is unconfirmed. CONDITIONAL(resource_policy) when the external bucket's
    policy may block writes from the analytics service's role. Inherit weakest from the contributing CanReadData
    edge; a CONDITIONAL CanReadData (e.g., analytics-service IAM unconfirmed) yields at best CONDITIONAL
    here. BLOCKED if the analytics service blocks UNLOAD to external buckets (Athena workgroup EnforceWorkgroupConfiguration
    with OutputLocation constraint) or an SCP restricts cross-account s3:PutObject.
  confidence: min(contributing_confidences) * 0.85
  derived_from:
  - ?principal CanReadData ?table (LF-governed table read, rule aws-lf-get-data-access-read)
  - ?principal HasPermission external_s3 (s3:PutObject on external destination)
  false_positive_note: "Exfiltration requires a write path to an external destination, not just the ability\
    \ to read. Confirm the external S3 bucket is actually external (different account or attacker-controlled).\
    \ Athena workgroup settings with EnforceWorkgroupConfiguration=true and a restricted OutputLocation\
    \ override the query-level UNLOAD destination \u2014 if the workgroup enforces a specific S3 path\
    \ within the same account, this path is CONDITIONAL or BLOCKED. Glue and EMR job targets are controlled\
    \ by the job/step definition \u2014 if the job definition is immutable (CanModifyCode is BLOCKED),\
    \ the external write path may not be available to the attacker without modifying the job first."
  narrative: '{principal.name} can read LF-governed table {table.name} (via Athena / Glue / EMR) and can
    direct query output to an external S3 destination (UNLOAD to s3://<attacker-bucket> or Glue/EMR job
    writing externally). This enables exfiltrating the governed table''s data out of the account''s LF-controlled
    boundary.'
move · open · esc close