aws-opensearch-exfiltrate-via-http
A principal with data-plane read access to an internet-exposed or reachable OpenSearch domain can exfiltrate search indices.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
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. |
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).'