Skip to main content

Unrestricted Elasticsearch Access Should Not Be Allowed

More Info:

No security group should allow unrestricted inbound access to TCP port 9200 (Elasticsearch).

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • AWS Startup Security Baseline
  • AWS Well Architected Framework
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • Cloudanix Best Practice
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • Reserve Bank of India (RBI) Cyber Security Framework
  • Reserve Bank of India (RBI) Master Direction – Information Technology Framework
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Using Console

To remediate the issue of unrestricted Elasticsearch access in AWS, you can follow the below steps:

  1. Login to the AWS console and navigate to the Elasticsearch service.
  2. Select the Elasticsearch domain that needs to be remediated.
  3. Click on the "Modify access" button under the "Actions" dropdown.
  4. In the "Configure access" section, select the option "Limit access to specific IP addresses or VPCs".
  5. Enter the IP addresses or CIDR blocks that should be allowed to access the Elasticsearch domain.
  6. Click on the "Submit" button to save the changes.

After completing these steps, the Elasticsearch domain will only be accessible from the specified IP addresses or VPCs, and unrestricted access will be restricted.

Using CLI

To remediate unrestricted Elasticsearch access in AWS using AWS CLI, follow these steps:

  1. Open the AWS CLI and run the following command to list all Elasticsearch domains in your account:

    aws es list-domain-names
  2. Identify the Elasticsearch domain that has unrestricted access.

  3. Run the following command to update the Elasticsearch domain's access policy to restrict access:

    aws es update-elasticsearch-domain-config --domain-name <domain-name> --advanced-security-options 'Enabled=true,InternalUserDatabaseEnabled=true,MasterUserOptions={MasterUserName=<master-username>,MasterUserPassword=<master-password>}'

    Replace <domain-name> with the name of the Elasticsearch domain and <master-username> and <master-password> with the credentials for the Elasticsearch master user.

  4. Verify that access to the Elasticsearch domain is now restricted by running the following command:

    aws es describe-elasticsearch-domain-config --domain-name <domain-name>

    This command should return the updated access policy for the Elasticsearch domain.

  5. Ensure that you have a backup of the Elasticsearch domain before making any changes to it.

Using Python

To remediate unrestricted Elasticsearch access in AWS using Python, you can follow these steps:

  1. Install the AWS SDK for Python (Boto3) using the following command:
pip install boto3
  1. Create an AWS Identity and Access Management (IAM) client using the following code snippet:
import boto3

# Create IAM client
iam = boto3.client('iam')
  1. Create an Elasticsearch service client using the following code snippet:
import boto3

# Create Elasticsearch service client
es = boto3.client('es')
  1. Use the Elasticsearch service client to retrieve the Elasticsearch domain policies using the following code snippet:
import boto3

# Create Elasticsearch service client
es = boto3.client('es')

# Retrieve Elasticsearch domain policies
response = es.describe_elasticsearch_domain_config(
DomainName='your-domain-name'
)

# Extract the Elasticsearch domain policies
policies = response['DomainConfig']['AccessPolicies']
  1. Check if the Elasticsearch domain policies allow unrestricted access using the following code snippet:
import json

# Check if Elasticsearch domain policies allow unrestricted access
if '{"Effect":"Allow","Principal":"*","Action":"es:*","Resource":"arn:aws:es:*:*:domain/your-domain-name/*"}' in policies:
# Remove the unrestricted access policy
new_policies = json.loads(policies)
new_policies['Statement'].remove({
'Effect': 'Allow',
'Principal': {'*'},
'Action': 'es:*',
'Resource': 'arn:aws:es:*:*:domain/your-domain-name/*'
})
new_policies = json.dumps(new_policies)
else:
# No remediation needed
new_policies = policies
  1. Use the Elasticsearch service client to update the Elasticsearch domain policies using the following code snippet:
import boto3

# Create Elasticsearch service client
es = boto3.client('es')

# Update Elasticsearch domain policies
response = es.update_elasticsearch_domain_config(
DomainName='your-domain-name',
AccessPolicies=new_policies
)
  1. Verify that the remediation was successful by checking the Elasticsearch domain policies again using the following code snippet:
import boto3

# Create Elasticsearch service client
es = boto3.client('es')

# Retrieve Elasticsearch domain policies
response = es.describe_elasticsearch_domain_config(
DomainName='your-domain-name'
)

# Extract the Elasticsearch domain policies
policies = response['DomainConfig']['AccessPolicies']

By following these steps, you can remediate unrestricted Elasticsearch access in AWS using Python.

Using Terraform
resource "aws_security_group" "elasticsearch_sg" {
name = "elasticsearch-sg"
description = "Security group for Elasticsearch"
vpc_id = aws_vpc.MY_VPC.id # replace with your VPC resource or ID
}

# KEEP a restricted IPv4 rule (example: only from a private subnet or trusted CIDR)
resource "aws_vpc_security_group_ingress_rule" "elasticsearch_ipv4_restricted" {
security_group_id = aws_security_group.elasticsearch_sg.id

ip_protocol = "tcp"
from_port = 9200
to_port = 9200

cidr_ipv4 = "TRUSTED_IPV4_CIDR" # e.g. "10.0.0.0/16" or a specific office IP
}

# OPTIONAL: restricted IPv6 rule, if needed
resource "aws_vpc_security_group_ingress_rule" "elasticsearch_ipv6_restricted" {
security_group_id = aws_security_group.elasticsearch_sg.id

ip_protocol = "tcp"
from_port = 9200
to_port = 9200

cidr_ipv6 = "TRUSTED_IPV6_CIDR" # e.g. "2001:db8:1234::/64"
}

Replace:

  • aws_vpc.MY_VPC.id with your VPC resource or ID.
  • TRUSTED_IPV4_CIDR / TRUSTED_IPV6_CIDR with the narrowest CIDR(s) that should access Elasticsearch.

To match the CLI fix, remove or edit any existing aws_vpc_security_group_ingress_rule (or inline ingress blocks) on this security group that have:

  • cidr_ipv4 = "0.0.0.0/0" with from_port = 9200, to_port = 9200, ip_protocol = "tcp", and/or
  • cidr_ipv6 = "::/0" with from_port = 9200, to_port = 9200, ip_protocol = "tcp".

This change updates only the rules on the existing security group; it does not force replacement of the security group itself. It is equivalent to permanently revoking the unrestricted IPv4/IPv6 ingress on TCP 9200 and may disrupt services that relied on open access.

Verification: terraform plan should show the offending ingress rule resources with cidr_ipv4 = "0.0.0.0/0" and/or cidr_ipv6 = "::/0" on port 9200 being destroyed or modified to the new restricted CIDRs, with no new rule reintroducing 0.0.0.0/0 or ::/0 on port 9200.

Additional Reading: