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.
- 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:
node-01-key.pem node-01.pem admin-key.pem admin.pem root-ca.pem
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 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 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:
/usr/share/elasticsearch/plugins/opendistro_security/securityconfig/internal_users.yml
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.