Skip to content

Elasticsearch exposed to the internet

Severity: criticalApplies to: Any reachable cluster

For most of the last decade, Elasticsearch was the single most common source of mass data breaches. Not because it was uniquely insecure, but because of a combination that turned out to be catastrophic at scale: it shipped with no authentication, it was easy to bind to a routable address, and it held precisely the data that makes headlines — aggregated logs, user records, entire application datasets.

The numbers were staggering. Individual exposed clusters leaked hundreds of millions of records at a time; in aggregate, billions. None of it required an exploit. Scanners found port 9200, made a GET request, and got everything.

Version 8.0 (2022) closed the default — security is now on out of the box. But three populations remain exposed: 7.x clusters (security off by default), modern clusters where someone turned security off to fix a connection error, and clusters bound to 0.0.0.0 behind a misconfigured firewall.

With security off, a single unauthenticated request does it:

Terminal window
curl http://your.es:9200/_cat/indices?v # every index, and its size
curl http://your.es:9200/_search?size=10000 # the documents
curl -X DELETE http://your.es:9200/_all # all of it, gone

No credential, no exploit, no privilege escalation. Read everything, or delete everything, in one line. The _cat/indices endpoint is a table of contents for the breach.

And like the MongoDB wave, open Elasticsearch attracted ransom crews: databases wiped and replaced with a single index demanding payment. As with MongoDB, paying is pointless — much of the time the data was never copied, only deleted, and there is nothing to return.

Worth knowing, because it explains why some old advice is so insistent about scripting.

Before the modern sandboxed scripting engine, Elasticsearch executed dynamic scripts in languages (MVEL, then Groovy) that could reach out of the sandbox. CVE-2014-3120 and CVE-2015-1427 turned an open cluster into remote code execution — a search query that ran shell commands on the host. Those were headline RCEs in their day.

Modern Elasticsearch uses Painless, a purpose-built sandboxed language, and the dangerous dynamic-scripting engines are gone. So a current open cluster is usually a total data compromise rather than host code execution — which is the same shape as MongoDB: the data is the loss, not the machine. That’s still catastrophic; it’s just not a shell.

Do not let that reassure you into leaving scripting-era versions running. A 7.x or older cluster that’s both open and outdated may still be exposed to the historic RCE paths, on top of everything else unpatched.

  1. Enable security — the wall that should have been there. On 8.x/9.x it’s a setting that was flipped off; put it back.
  2. Bind to a private interface — off 0.0.0.0, onto the one interface your clients use.
  3. Firewall 9200 and 9300 — an unreachable cluster needs no login, and 9300 should never be reachable from outside your node network.
  4. Give apps scoped credentials — so a leak later isn’t the whole cluster.

Steps 1 and 2 are settings plus a restart. Do them before you finish reading.