Back to Checks
EC2 instance does not allow ingress from the Internet to Elasticsearch and Kibana ports (TCP 9200, 9300, 5601)
ec2_instance_port_elasticsearch_kibana_exposed_to_internet
Service: ec2Severity: critical
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsEc2Instance
EC2 instances with Elasticsearch/Kibana ports (9200, 9300, 5601) exposed to the Internet through inbound security group rules.
Assesses reachability considering instance public IP and subnet to reflect real exposure.
Risk
Public access to Elasticsearch/Kibana can lead to:
- Unauthorized queries or dashboard viewing confidentiality loss
- Index changes or cluster control via
9300integrity impact - Scans and bulk queries availability degradation
Enables data exfiltration and lateral movement.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks ec2_instance_port_elasticsearch_kibana_exposed_to_internetRecommendation
Apply least privilege to network exposure:
- Restrict
9200,9300,5601to trusted sources or keep them private - Use private subnets, VPN/peering, or bastion/SSM for admin access
- Enforce authentication and TLS on Elasticsearch/Kibana
- Avoid public IPs unless strictly required
Remediation
CLI
aws ec2 revoke-security-group-ingress --group-id <SECURITY_GROUP_ID> --ip-permissions '[{"IpProtocol":"tcp","FromPort":9200,"ToPort":9200,"IpRanges":[{"CidrIp":"0.0.0.0/0"}]},{"IpProtocol":"tcp","FromPort":9300,"ToPort":9300,"IpRanges":[{"CidrIp":"0.0.0.0/0"}]},{"IpProtocol":"tcp","FromPort":5601,"ToPort":5601,"IpRanges":[{"CidrIp":"0.0.0.0/0"}]}]'Terraform
# Terraform: restrict Elasticsearch/Kibana ports to a private CIDR (not the Internet)
resource "aws_security_group" "<example_resource_name>" {
name = "<example_resource_name>"
vpc_id = "<example_resource_id>"
# CRITICAL: restrict sources; do NOT use 0.0.0.0/0 or ::/0
ingress {
from_port = 9200
to_port = 9200
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
from_port = 9300
to_port = 9300
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
ingress {
from_port = 5601
to_port = 5601
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
}NativeIaC
# CloudFormation: restrict Elasticsearch/Kibana ports to a private CIDR (not the Internet)
Resources:
<example_resource_name>:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Restrict Elasticsearch/Kibana ports
VpcId: <example_resource_id>
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 9200
ToPort: 9200
CidrIp: 10.0.0.0/8 # CRITICAL: do not use 0.0.0.0/0 or ::/0; restrict to internal CIDR
- IpProtocol: tcp
FromPort: 9300
ToPort: 9300
CidrIp: 10.0.0.0/8 # CRITICAL: restrict source to stop Internet exposure
- IpProtocol: tcp
FromPort: 5601
ToPort: 5601
CidrIp: 10.0.0.0/8 # CRITICAL: restrict source to stop Internet exposureOther
1Open the AWS Console and go to EC2 > Security Groups
2Select the security group attached to the instance
3In Inbound rules, find any rule allowing TCP 9200, 9300, or 5601 from 0.0.0.0/0 or ::/0
4Edit inbound rules and either delete those rules or change the source to a restricted CIDR (e.g., your internal network)
5Save rules
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
from prowler.providers.aws.services.ec2.lib.instance import get_instance_public_status
from prowler.providers.aws.services.ec2.lib.security_groups import check_security_group
from prowler.providers.aws.services.vpc.vpc_client import vpc_client
class ec2_instance_port_elasticsearch_kibana_exposed_to_internet(Check):
# EC2 Instances with Elasticsearch/Kibana ports open to the Internet will be flagged as FAIL with a severity of medium if the instance has no public IP, high if the instance has a public IP but is in a private subnet, and critical if the instance has a public IP and is in a public subnet.
def execute(self):
findings = []
check_ports = [9200, 9300, 5601]
for instance in ec2_client.instances:
report = Check_Report_AWS(metadata=self.metadata(), resource=instance)
report.status = "PASS"
report.status_extended = f"Instance {instance.id} does not have Elasticsearch/Kibana ports open to the Internet."
is_open_port = False
if instance.security_groups:
for sg in ec2_client.security_groups.values():
if sg.id in instance.security_groups:
for ingress_rule in sg.ingress_rules:
if check_security_group(
ingress_rule, "tcp", check_ports, any_address=True
):
# The port is open, now check if the instance is in a public subnet with a public IP
report.status = "FAIL"
(
report.status_extended,
report.check_metadata.Severity,
) = get_instance_public_status(
vpc_client.vpc_subnets,
instance,
"Elasticsearch/Kibana",
)
is_open_port = True
break
if is_open_port:
break
findings.append(report)
return findings