How to set up Elasticsearch so that there are no leaks

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

Let's make a reservation right away that in our practice we use Elasticsearch to store logs and analyze logs of information security tools, OS and software in our IaaS platform that meets the requirements of 152-FZ, Cloud-152. 

How to set up Elasticsearch so that there are no leaks

Checking if the database is β€œsticking out” on the Internet

In most 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, let's deal with publishing on the Internet. Why is it so? The fact is that for more flexible work Elasticsearch recommended create a cluster of three servers. In order 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 is easy to check if there is access to the database from the outside. Just type in the browser http://[IP/Имя Elasticsearch]:9200/_cat/nodes?v

If it turns out to go in, then run to close.

Protecting the connection to the database

Now we will make it so that it is 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 free use).

The good news is that in the fall of 2019, Amazon opened up its developments that overlap with the X-Pack. The database connection authentication feature has become available under a free license for Elasticsearch 7.3.2., and a new release for Elasticsearch 7.4.0 is already in the works.

Installing this plugin is easy. 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 connection port to the database changes. It enables SSL encryption. In order for the cluster servers to continue to work with each other, you need to configure the interaction between them using SSL.

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

  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, 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 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

  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 signature request:

    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 lay out the certificate between Elasticsearch nodes in a folder:

    /etc/elasticsearch/


    we need files:

            node-01-key.pem
    	node-01.pem
    	admin-key.pem
    	admin.pem
    	root-ca.pem

  11. Customize /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                                                                                                                                                                                         
    	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

Change internal user passwords

  1. Use the command below to print the hash of the password to the console:

    sh ${OD_SEC}/tools/hash.sh -p [ΠΏΠ°Ρ€ΠΎΠ»ΡŒ]

  2. Change the hash in the file to the received one:

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

Setting up a firewall in the OS

  1. We allow the launch of the firewall:

    systemctl enable firewalld

  2. Let's run it:

    systemctl start firewalld

  3. Allow connection to Elasticsearch:

    firewall-cmd --set-default-zone work
    firewall-cmd --zone=work --add-port=9200/TCP --permanent

  4. Reload the firewall rules:

    firewall-cmd --reload

  5. We derive working rules:

    firewall-cmd --list-all

Applying 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 have been applied:

    curl -XGET https://[IP/Имя Elasticsearch]:9200/_cat/nodes?v -u admin:[ΠΏΠ°Ρ€ΠΎΠ»ΡŒ] --insecure

Everything, these are the minimum settings that close Elasticsearch from unauthorized connections.

Source: habr.com

Add a comment