How to configure Elasticsearch so that there are no leaks

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

Weโ€™ll immediately make a reservation that in our practice we use Elasticsearch to store logs and analyze logs of information protection tools, OS and software in our IaaS platform that meets the requirements of 152-, Cloud-152. 



Check if the database is โ€œstickingโ€


In most of the known cases of leaks ( here , here ), the attacker gained 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, weโ€™ll deal with publishing on the Internet. Why is this so? The fact is that for more flexible operation of Elasticsearch, it is recommended to create a cluster of three servers. In order for the databases to communicate with each other, you need to open the ports. As a result, administrators do not restrict access to the database, and you can connect to the database from anywhere. Checking if there is external access to the database is easy. Just enter http: // [IP / Elasticsearch Name]: 9200 / _cat / nodes? In the browser ? V

If you manage to log in, then run to close.

We protect 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 set of X-Pack plugins (1 month of free use).

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

Installing this plugin is easy. We go into 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 -

We configure interaction between servers through SSL


When installing the plugin, the configuration of the database connection port changes. It includes SSL encryption. In order for the cluster servers to continue working with each other, you need to configure the interaction between them using SSL.

Trust between hosts can be established with or without your own certification authority. With the first method, everything is clear: you just need to contact a specialist in CA. We proceed immediately 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
  3. We sign the root certificate. Keep it as the apple of your eye: if it is lost or compromised, the 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
  4. 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
  5. Create a request for signing a certificate:

    openssl req -new -subj "/C=RU/ST=Moscow/O=Moscow Inc./CN=${DOMAIN_CN}/CN=admin " \
    -key admin-key.pem -out admin.csr
  6. 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
  7. 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
  8. Create a request for signature:

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

    openssl x509 -req -in node.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial \
    -sha256 -out node.pem
  10. We decompose the certificate between Elasticsearch nodes into the folder:

    /etc/elasticsearch/

    we need the files:

            node-01-key.pem
    	node-01.pem
    	admin-key.pem
    	admin.pem
    	root-ca.pem
  11. Set up /etc/elasticsearch/elasticsearch.yml - change the name of the certificate files to the ones 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                                                                                                                                                                                         
    	opendistro_security.authcz.admin_dn:                                                                                                                                                                                                               
    	  โˆ’ CN=admin,CN=example.com,O=Moscow Inc.,ST=Moscow,C=RU                                                                                                                                                                                                  
    	opendistro_security.nodes_dn:                                                                                                                                                                                                                      
    	  โˆ’ CN=node-01.example.com,O=Moscow Inc.,ST=Moscow,C=RU

We change passwords of internal users


  1. Using the command below, we display the password hash in the console:

    sh ${OD_SEC}/tools/hash.sh -p []
  2. Change the hash in the file to the one received:

    /usr/share/elasticsearch/plugins/opendistro_security/securityconfig/internal_users.yml

Configure the firewall in OS


  1. Allow the launch of the firewall:

    systemctl enable firewalld
  2. Run it:

    systemctl start firewalld
  3. We allow connection to Elasticsearch:

    firewall-cmd --set-default-zone work
    firewall-cmd --zone=work --add-port=9200/TCP --permanent
  4. Rebooting firewall rules:

    firewall-cmd --reload
  5. We derive the working rules:

    firewall-cmd --list-all

Apply all our changes to Elasticsearch


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

    export  OD_SEC="/usr/share/elasticsearch/plugins/opendistro_security/"
  2. Run a script that will update passwords and check 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
  3. Check if the changes applied:

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

That's all, these are the minimum settings that block Elasticsearch from an unauthorized connection.

Source: https://habr.com/ru/post/undefined/


All Articles