Remediation Guides

Elasticsearch Unrestricted Access (Nessus 101025): How to Enable Authentication with xpack.security.enabled

26 September 2026 9 min read

Elasticsearch Unrestricted Access Information Disclosure (Nessus plugin 101025) means a scanner queried the Elasticsearch REST API, usually on TCP 9200, without any credentials. Fix it by setting xpack.security.enabled: true in elasticsearch.yml, giving the built-in users strong passwords, enabling TLS and limiting who can reach ports 9200 and 9300.

What the scanner is actually detecting

The finding comes from Tenable Nessus plugin 101025, titled Elasticsearch Unrestricted Access Information Disclosure. It is a remote check: Nessus first identifies an Elasticsearch service, then reports that the service lets an unauthenticated client access its data. Tenable’s recommended solution is to enable native user authentication or integrate an external user store such as LDAP or Active Directory.

Field Value on the Tenable plugin page
Plugin name Elasticsearch Unrestricted Access Information Disclosure
Plugin ID 101025 (elasticsearch_unprotected.nasl)
Severity Medium
Type and family Remote, CGI abuses
Required KB item installed_sw/Elasticsearch
Published June 23, 2017

The plugin predates May 2019, when Elastic moved TLS, the file and native realms and role-based access control into the free Basic license with versions 6.8.0 and 7.1.0. Today the finding usually points to one of four states:

  • Elasticsearch 7.x on the Basic license, where security features are disabled by default and nobody turned them on.
  • Elasticsearch 8.x or 9.x with security explicitly switched off, most often through xpack.security.enabled: false copied from a development Docker Compose file.
  • Anonymous access configured with roles that can read indices.
  • Versions before 6.8.0, or 7.0.x, where the Basic license has no security features at all.

Real-world risk

With security disabled, every REST API is open to anyone who can reach the HTTP port. That means a client can:

  • Read every index through _search. Log clusters often hold personal data and secrets that applications logged by mistake.
  • Change or delete data, including dropping whole indices with a single DELETE request.
  • Change cluster settings and read cluster metadata such as node names, addresses and installed plugins.

Tenable rates the plugin Medium, and on supported versions the impact is to the data rather than the operating system. How urgent it is depends on reachability and on what the indices contain. A cluster reachable from the Internet should be fixed today, and it is worth checking your external attack surface management scope to learn how it became reachable. An internal cluster is lower risk, but any compromised host that can reach port 9200 gets full access.

How to confirm it on the host

From another machine, ideally the scanner’s segment:

curl -s http://<host>:9200/
# JSON with "cluster_name" and "version" = no authentication, finding is valid
# HTTP 401 with "security_exception" = authentication is enforced

curl -s 'http://<host>:9200/_cat/indices?v'
curl -s 'http://<host>:9200/_xpack?pretty'
# "security" : { "available" : true, "enabled" : false } = security is off

If the plain HTTP request is reset or returns an empty reply, the node probably serves HTTPS only; repeat with https:// and -k to see whether it still answers without credentials.

On the Elasticsearch host (package installs keep the configuration in /etc/elasticsearch):

grep -nE '^[[:space:]]*(xpack.security|network.host|http.host|discovery.type)' /etc/elasticsearch/elasticsearch.yml
ss -tlnp | grep -E ':(9200|9300)b'

For containers, check the published ports and the environment:

docker ps --format '{{.Names}} {{.Ports}}' | grep 9200
docker inspect <container> --format '{{range .Config.Env}}{{println .}}{{end}}' | grep -i security

How to fix it

Before you start

List every client that talks to the cluster without credentials today: Kibana, Logstash, Beats and Elastic Agent, application code, backup and snapshot scripts, cron jobs and monitoring exporters. Each one needs a user and password after the change. Back up the configuration with cp -p /etc/elasticsearch/elasticsearch.yml /etc/elasticsearch/elasticsearch.yml.bak.

Elasticsearch 8.x and 9.x

Security is enabled automatically on first start, so the finding means someone disabled it. Change the setting in elasticsearch.yml on every node:

xpack.security.enabled: true
# single-node deployments only:
discovery.type: single-node

If the setting was present before the first start, the automatic setup (certificates and the generated elastic password) was skipped, so a multi-node cluster also needs the transport TLS steps below. If the file already contains xpack.security.transport.ssl and xpack.security.http.ssl blocks from auto-configuration, keep them. Restart Elasticsearch, then set passwords for the built-in users:

sudo systemctl restart elasticsearch
sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u kibana_system

The tool generates a strong password by default; add -i to type your own. It needs the node running and the file realm enabled, which is the default.

Elasticsearch 7.1 to 7.17

Add the same xpack.security.enabled: true line (plus discovery.type: single-node for a single node), restart, and set the built-in passwords once for the whole cluster:

sudo /usr/share/elasticsearch/bin/elasticsearch-setup-passwords interactive

Use auto instead of interactive for random passwords. Elastic notes the tool can only run once: after the elastic password is set it refuses to run again, so store the output immediately.

Versions before 6.8.0, and 7.0.x

These releases have no authentication in the Basic license and are no longer supported. Plan an upgrade, and until then restrict network access as described below.

Transport TLS for multi-node clusters

With security enabled, a node that binds to a non-loopback address runs in production mode, and it will not start without TLS on the transport layer (port 9300). Create a CA and a node certificate once:

cd /usr/share/elasticsearch
sudo bin/elasticsearch-certutil ca
sudo bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12

Copy elastic-certificates.p12 to /etc/elasticsearch/ on every node, readable by the elasticsearch user, and add:

xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

If you protected the certificate with a password, store it in the keystore on each node:

sudo bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
sudo bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password

This needs a full cluster restart, because nodes with transport TLS cannot talk to nodes without it.

HTTPS on port 9200

Without HTTPS, clients send the password in every request header in cleartext. Generate HTTP certificates with sudo bin/elasticsearch-certutil http, which produces elasticsearch-ssl-http.zip with an http.p12 per node. Place it in the config directory and add:

xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12
sudo bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password

In kibana.yml, point Kibana at https:// and trust the CA: elasticsearch.hosts: https://<es-host>:9200 and elasticsearch.ssl.certificateAuthorities: $KBN_PATH_CONF/elasticsearch-ca.pem. Set elasticsearch.username: “kibana_system” and store its password with bin/kibana-keystore add elasticsearch.password.

Docker containers

Remove xpack.security.enabled=false (or ES_SETTING_XPACK_SECURITY_ENABLED=false) from the run command or Compose file (add discovery.type=single-node for a single existing container). On new deployments, supply the elastic password from a secret with ELASTIC_PASSWORD_FILE. For an existing container, reset it after enabling security:

docker exec -it es01 /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic

Publish the port only where it is needed, for example -p 127.0.0.1:9200:9200, or not at all when clients run on the same Docker network. Docker’s documentation notes that published container ports bypass ufw rules.

Restrict network exposure

network.host defaults to loopback, but security auto-configuration in 8.x writes http.host: 0.0.0.0, so review both. Bind to the private interface clients use, open 9200 only to application and Kibana hosts, and keep 9300 between cluster nodes. With firewalld:

firewall-cmd --permanent --remove-port=9200/tcp
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.5.0/24" port port="9200" protocol="tcp" accept'
firewall-cmd --reload

With ufw, add the allow rule before the deny:

ufw allow from 10.0.5.0/24 to any port 9200 proto tcp
ufw deny 9200/tcp

LDAP or Active Directory (optional)

Tenable also suggests external user stores. LDAP and Active Directory realms are configured under xpack.security.authc.realms; check that your subscription covers them, and enable native security first.

How to verify the fix and rescan

  1. From a remote machine, curl -s http://<host>:9200/ should fail with HTTP 401, or with a TLS error when HTTPS is enforced.
  2. With credentials it should succeed: curl –cacert <ca-file> -u elastic https://<host>:9200. The CA file is http_ca.crt on auto-configured 8.x nodes, or elasticsearch-ca.pem from the certutil http bundle. curl prompts for the password, which keeps it out of shell history.
  3. curl –cacert <ca-file> -u elastic ‘https://<host>:9200/_xpack?pretty’ should show security as enabled.
  4. Check Kibana, Logstash, Beats and application logs for 401 errors.
  5. Rescan with the same Nessus policy and scanner. Plugin 101025 should no longer be reported. If the firewall now blocks the scanner entirely, the rescan proves only that one path is closed.

What can break and how to roll back

  • Clients without credentials start failing with 401: Kibana, Logstash, Beats, applications and snapshot scripts.
  • HTTP to HTTPS breaks every client URL that still says http://.
  • Multi-node clusters will not form if transport TLS settings differ between nodes, and the change needs a full cluster restart.
  • Least privilege takes planning: do not hand the elastic superuser to applications; create users with only the index privileges they need.

To roll back, restore elasticsearch.yml.bak on every node and restart (a full cluster restart for multi-node clusters). Keep the firewall rules in place while you fix the clients, and treat the rollback as temporary.

Common false positive reasons

  • A different instance answered. http.port defaults to the range 9200 to 9300, so a second node on the same host may sit on 9201. Match the port in the plugin output.
  • The change never loaded. The file was edited but the node not restarted, or the service reads a different path set through ES_PATH_CONF.
  • A reverse proxy passes requests through. A proxy in front of the cluster without its own authentication is a real finding, not a false positive.
  • Anonymous access has read roles. Also real: remove the roles or disable anonymous access.
  • It is not Elasticsearch. Compatible forks such as OpenSearch use their own security plugin, so the xpack settings in this guide do not apply there.

FAQ

Do I need a paid license to enable authentication?

No. Since 6.8.0 and 7.1.0, the free Basic license includes TLS, native and file realm users and role-based access control.

Is a firewall rule enough to close the finding?

It removes the scanner’s path, but anyone on an allowed network still gets full access. Enable authentication and use the firewall as a second layer.

I lost the elastic password on 8.x. What now?

Run elasticsearch-reset-password -u elastic on a node. It works through a temporary file realm user, so you do not need the old password.

Is HTTPS required to close plugin 101025?

The plugin checks for unauthenticated access, so authentication alone closes it. HTTPS is still strongly recommended because Basic authentication sends credentials with every request.

Tracking this finding across many hosts

Unprotected Elasticsearch tends to reappear as test clusters and containers are rebuilt from old Compose files. A platform such as SITEY can import Nessus results (as an uploaded .nessus export) alongside other scanners, draft a host-specific configuration change that its Linux agent deploys only after human approval, and re-test each Nessus finding to confirm plugin 101025 has closed.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing