5/5 - (1 vote)

Over the past year, there have been many leaks from Elasticsearch databases. In many cases, personal data was stored in the database. These leaks could have been avoided if, after deploying the database, the administrators took the trouble to check a few simple settings. Today we’ll talk about them.

Let’s make a notice right away that in our practice we use Elasticsearch for storing logs and analyzing the logs of information security tools, OS and software in our IaaS platform.

Checking whether the database is  “out” on the Internet

In most of the known cases of leaks, the attacker got access to the data simply and unpretentiously: the database was published on the Internet, and it was possible to connect to it without authentication.

First, let’s deal with publishing on the Internet. Why does this happen? The fact is that for more flexible Elasticsearch operation, it is recommended to create a cluster of three servers. For the databases to communicate with each other, you need to open ports. As a result, administrators do not restrict access to the database in any way, and you can connect to the database from anywhere. It’s easy to check if the database is accessible from the outside.

Just enter http: // [IP / Elasticsearch Name]: 9200 / _cat / nodes? V

If you manage to enter, directly close.

Securing the connection to the database

Now we will make it impossible to connect to the database without authentication.

Elasticsearch has an authentication module that restricts access to the database, but it is only in the paid X-Pack plugin (1 month free use).

The good news is that in the fall of 2019, Amazon revealed its developments that overlap with the X-Pack. The authentication function when connecting to the database has become available under a free license for the Elasticsearch version 7.3.2., And a new release for Elasticsearch 7.4.0 is already in the works.

Installing this plugin is simple. We go to the server console and connect the repository:

RPM Based:

curl https://d3g5vo6xdbdb9a.cloudfront.net/yum/opendistroforelasticsearch-artifacts.repo -o /etc/yum.repos.d/opendistroforelasticsearch-artifacts.repo

yum update

yum install opendistro-security

DEB Based:

wget -qO - https://d3g5vo6xdbdb9a.cloudfront.net/GPG-KEY-opendistroforelasticsearch | sudo apt-key add -

Setting up communication between servers via SSL

When installing the plugin, the configuration of the port for connecting to the base is changed. SSL encryption is enabled on it. In order for the cluster servers to continue to work with each other, you need to set up communication between them using SSL.

Trust between hosts can be established with or without your own SA. With the first method, everything is clear: you just need to contact the SA specialists. Let’s go straight to the second.

  1. Create a variable with the fully qualified domain name:
export DOMAIN_CN = "example.com"

2. Create a private key:

openssl genrsa -out root-ca-key.pem 4096

Sign the root certificate. Keep it like the apple of your eye: if it is lost or compromised, trust between all hosts will need to be reconfigured.

openssl req -new -x509 -sha256 \ -subj "/ C = RU / ST = Moscow / O = Moscow, Inc./CN=$ {DOMAIN_CN}" \
-key root-ca-key.pem -out root-ca.pem

Create an admin key:

openssl genrsa -out admin-key-temp.pem 4096
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem -topk8 -nocrypt \
-v1 PBE-SHA1-3DES -out admin-key.pem

Create a certificate signing request:

openssl req -new -subj "/ C = RU / ST = Moscow / O = Moscow Inc./CN=$ {DOMAIN_CN }/CN=admin" \
-key admin-key.pem -out admin.csr

Create an administrator certificate:

openssl x509 -req -extensions usr_cert -in admin.csr -CA root-ca.pem \
-CAkey root-ca-key.pem -CAcreateserial -sha256 -out admin.pem
We create certificates for the Elasticsearch node:

export NODENAME = "node-01"
openssl genrsa -out $ {NODENAME} -key-temp.pem 4096
openssl pkcs8 -inform PEM -outform PEM -in $ {NODENAME} -key-temp.pem -topk8 -nocrypt \
-v1 PBE-SHA1-3DES -out $ {NODENAME} -key.pem

Create a signature request:

openssl req -new -subj "/ C = RU / ST = Moscow / O = Moscow Inc./CN=$ [NODENAME].
-addext "subjectAltName = DNS: $ {NODENAME}. $ {DOMAIN_CN}, DNS: www. $ {NODENAME}. $ {DOMAIN_CN}" \
-key $ {NODENAME} -key.pem -out $ {NODENAME} .csr

Sign the certificate:

openssl x509 -req -in node.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial \
-sha256 -out node.pem

Put the certificate to Elasticsearch nodes into a folder:

/ etc / elasticsearch /

we need files:


Configure /etc/elasticsearch/elasticsearch.yml – change the name of the files with certificates, to those generated by us:

opendistro_security.ssl.transport.pemcert_filepath: node-01.pem                                                                                                                                                                                    
	opendistro_security.ssl.transport.pemkey_filepath: node-01-key.pem                                                                                                                                                                                 
	opendistro_security.ssl.transport.pemtrustedcas_filepath: root-ca.pem                                                                                                                                                                              
	opendistro_security.ssl.transport.enforce_hostname_verification: false                                                                                                                                                                             
	opendistro_security.ssl.http.enabled: true                                                                                                                                                                                                         
	opendistro_security.ssl.http.pemcert_filepath: node-01.pem                                                                                                                                                                                         
	opendistro_security.ssl.http.pemkey_filepath: node-01-key.pem                                                                                                                                                                                      
	opendistro_security.ssl.http.pemtrustedcas_filepath: root-ca.pem                                                                                                                                                                                   
	opendistro_security.allow_unsafe_democertificates: false                                                                                                                                                                                           
	opendistro_security.allow_default_init_securityindex: true                                                                                                                                                                                         
	  − CN=admin,CN=example.com,O=Moscow Inc.,ST=Moscow,C=RU                                                                                                                                                                                                  
	  − CN=node-01.example.com,O=Moscow Inc.,ST=Moscow,C=RU

Change passwords for internal users.

Using the command below, we output the password hash to the console:

sh $ {OD_SEC} /tools/hash.sh -p [password]

Change the hash in the file to the received one:


Configure a firewall in the OS

Allow the launch of the firewall:

systemctl enable firewalld

Launch it:

systemctl start firewalld

Allowing connection to Elasticsearch:

firewall-cmd --set-default-zone work
firewall-cmd --zone = work --add-port = 9200 / TCP --permanent
Reload the firewall rules:

firewall-cmd --reload

Display working rules:

firewall-cmd --list-all

Apply all our changes to Elasticsearch.

Create a variable with the full path to the plugin folder:

export OD_SEC = "/ usr / share / elasticsearch / plugins / opendistro_security /"

Run the script that will update passwords and check the settings:

$ {OD_SEC} /tools/securityadmin.sh -cd $ {OD_SEC} / securityconfig / \
-icl -nhnv -cacert /etc/elasticsearch/root-ca.pem \
-cert /etc/elasticsearch/admin.pem \
-key /etc/elasticsearch/admin-key.pem
Check if the changes have been applied:

curl -XGET https: // [IP / Elasticsearch Name]: 9200 / _cat / nodes? v -u admin: [password] --insecure

That’s all, these are the minimum settings that close Elasticsearch from unauthorized connections.