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.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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 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. |
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.'