aws-opensearch-exfiltrate-via-http

A principal with data-plane read access to an internet-exposed or reachable OpenSearch domain can exfiltrate search indices.

derived aws emits CanExfiltrate

match

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

{'principal': None} CanReadData {'domain': None}

where

node_type(?domain) == SearchService ?domain is ExposedToInternet OR ?principal has network reach to ?domain

emit

source typeIdentity
target typeSearchService
source<principal>
target<OpenSearch domain (SearchService)>
permissionses:ESHttpGet
conditionsiam_permission resource_policy network_reachability
state logicACTIVE when the principal has CanReadData on the domain AND network reach is confirmed (either the domain is ExposedToInternet or the principal is a compute resource in-network to a VPC endpoint, or has signed reach to a public endpoint). CONDITIONAL(network_reachability) if network reach is uncertain. BLOCKED if CanReadData is BLOCKED or network reach is unavailable. CanExfiltrate inherits the state from CanReadData; if CanReadData is CONDITIONAL on network_reachability, so is CanExfiltrate.

Narrative

{principal.name} can exfiltrate search indices from OpenSearch domain {domain.name} by issuing bulk _search / _scroll queries via HTTP GET and moving the data out of the boundary (cross-account, internet, external storage).

Raw rule rules/derived/aws/opensearch.yaml

id: aws-opensearch-exfiltrate-via-http
emits: CanExfiltrate
description: A principal with data-plane read access to an internet-exposed or reachable OpenSearch domain
  can exfiltrate search indices.
match:
- - principal: null
  - CanReadData
  - domain: null
where:
- node_type(?domain) == SearchService
- ?domain is ExposedToInternet OR ?principal has network reach to ?domain
emit:
  source_type: Identity
  target_type: SearchService
  source: <principal>
  target: <OpenSearch domain (SearchService)>
  permissions:
  - es:ESHttpGet
  conditions:
  - iam_permission
  - resource_policy
  - network_reachability
  state_logic: ACTIVE when the principal has CanReadData on the domain AND network reach is confirmed
    (either the domain is ExposedToInternet or the principal is a compute resource in-network to a VPC
    endpoint, or has signed reach to a public endpoint). CONDITIONAL(network_reachability) if network
    reach is uncertain. BLOCKED if CanReadData is BLOCKED or network reach is unavailable. CanExfiltrate
    inherits the state from CanReadData; if CanReadData is CONDITIONAL on network_reachability, so is
    CanExfiltrate.
  false_positive_note: Do not emit if the principal has only CanRead (config-level) without CanReadData
    (data-plane). VPC domains require explicit network reach evidence (VPC peering, PrivateLink, compute
    foothold in-VPC); do not emit ACTIVE without that. Public endpoints are trivially reachable.
  narrative: '{principal.name} can exfiltrate search indices from OpenSearch domain {domain.name} by issuing
    bulk _search / _scroll queries via HTTP GET and moving the data out of the boundary (cross-account,
    internet, external storage).'
move · open · esc close