# Elasticsearch enumeration via REST API

- **URL:** https://hackindex.io/services/elasticsearch/enumeration/elasticsearch-enumeration-via-rest-api
- **Path:** Elasticsearch > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/elasticsearch/enumeration.md)
- **Published:** 2026-01-18
- **Updated:** 2026-01-18

Elasticsearch exposes a wide REST surface on TCP/9200. If it’s unauthenticated or anonymously readable, you can pull cluster metadata, index structure, and often data.

## Service discovery and unauth check

```bash
nmap -sV -p $PORT $TARGET_IP
```

Hit the root endpoint first. It usually gives you `cluster_name` and `version` when readable.

```bash
curl -sS -i "http://$TARGET_IP:$PORT/"
```

Interpretation:

- `200` with JSON = you can enumerate immediately.
- `401` = auth enforced (still worth checking for proxy leaks or misrouted endpoints, but assume you need creds).
- `403` = reachable but your identity lacks privileges (common with anonymous user/limited role).

Typical readable banner shape:

```json
{
  "name": "node-1",
  "cluster_name": "prod-es",
  "cluster_uuid": "…",
  "version": { "number": "8.x.x", "build_flavor": "default" }
}
```

### Virtual host and TLS variants

If it’s behind a reverse proxy or uses a name-based vhost:

```bash
curl -sS -i "http://$TARGET_IP:$PORT/" -H "Host: $DOMAIN"
```

If it’s TLS on 9200:

```bash
curl -sS -i "https://$TARGET_IP:$PORT/" -k
```

## Transport port exposure (9300)

9300 is the transport protocol and should be cluster-internal. Open 9300 is a useful signal even if you don’t use it for REST enumeration.

```bash
nmap -p 9300 $TARGET_IP
```

What to do with it:

- If 9300 is exposed beyond the cluster network, flag it. It often correlates with weak network controls and mis-scoped security groups.

## Cluster and node enumeration

Cluster health gives you topology signals fast (single node vs multi-node, shard state).

```bash
curl -sS "http://$TARGET_IP:$PORT/_cluster/health?pretty"
```

What changes decisions:

- `number_of_nodes: 1` often means “all eggs in one basket” and simpler scoping for data exposure.
- `status: red/yellow` doesn’t block enumeration but can explain timeouts or partial results.

Cluster settings can leak internal hostnames, repo paths, and operational knobs.

```bash
curl -sS "http://$TARGET_IP:$PORT/_cluster/settings?pretty"
```

Nodes list is where internal IPs and hostnames usually show up.

```bash
curl -sS "http://$TARGET_IP:$PORT/_nodes?pretty"
```

If allowed, node stats gives OS/JVM/plugin detail and is noisy but high value for environment fingerprinting.

```bash
curl -sS "http://$TARGET_IP:$PORT/_nodes/stats?pretty"
```

Interpretation:

- Internal RFC1918 IPs, hostnames, availability zones, and plugin names help pivot into the underlying platform footprint.
- Plugin presence can hint at data sources (ingest-attachment, repository plugins, cloud plugins).

## Index and mapping enumeration

Get the index list first. `_cat` endpoints are meant for humans and are perfect for terminal enumeration.

```bash
curl -sS "http://$TARGET_IP:$PORT/_cat/indices?v"
curl -sS "http://$TARGET_IP:$PORT/_cat/aliases?v"
```

What to do with it:

- Prioritize indices with obvious business data (`users`, `customer`, `auth`, `payments`, `logs`, `prod`).
- Note backing indices for data streams and anything with unexpectedly high doc counts or large store sizes.

Mappings give you field names, which are the fastest “what data lives here” signal.

```bash
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_mapping?pretty"
```

Settings can reveal lifecycle policies, analyzers, index templates usage, and shard/replica choices.

```bash
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_settings?pretty"
```

## Document and data sampling

Pull a small sample without trying to scroll the whole index.

```bash
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_search?size=5&pretty"
```

If query-string search is enabled, quick keyword probes can surface obvious secrets fast, but don’t assume every cluster allows it.

```bash
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_search?q=password&pretty"
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_search?q=token&pretty"
curl -sS "http://$TARGET_IP:$PORT/<index_name>/_search?q=apikey&pretty"
```

What changes decisions:

- If hits include plaintext creds, JWTs, API keys, session IDs, or reset links, stop broad enumeration and start evidence capture with tight scoping.
- If it’s mostly logs, shift to searching for auth headers, cookies, and upstream URLs.

Counts help you prioritize impact quickly.

```bash
curl -sS "http://$TARGET_IP:$PORT/_cat/count?v"
```

## Security and auth context

This endpoint cleanly tells you whether the server considers you authenticated. A `401` is the normal “security on, no creds” response.

```bash
curl -sS -i "http://$TARGET_IP:$PORT/_security/_authenticate"
```

Interpretation:

- `401` = auth enforced.
- `200` with JSON user info = anonymous access or auth bypass via proxy/routing misconfig. Treat as full-read risk.

### X-Pack endpoints and version drift

> `/_xpack` is legacy and removed in newer versions. Prefer current endpoints like `/ _security/*`, `/ _license`, and other documented APIs.

If you’re on an older deployment that still exposes it, expect it to be privilege-gated:

```bash
curl -sS -i "http://$TARGET_IP:$PORT/_xpack?pretty"
```

If you need a modern “what features exist” signal and it’s accessible, check the features API:

```bash
curl -sS "http://$TARGET_IP:$PORT/_features?pretty"
```

## References

- [Authenticate a user](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-security-authenticate) - 401 vs 200 behavior for auth context
- [CAT indices API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-cat-indices) - Index listing output and intended usage
- [Migrating to 8.0](https://www.elastic.org.cn/docs/8.1/www.elastic.co/guide/en/elasticsearch/reference/current/migrating-8.0.html) - Notes on removed _xpack endpoints
- [Get features API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-features-get-features) - Feature listing endpoint / _features
