Back to Checks
Security group does not allow ingress from 0.0.0.0/0 or ::/0 to Postgres TCP port 5432
ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432
Service: ec2Severity: high
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsEc2SecurityGroup
EC2 security groups are evaluated for inbound rules that expose Postgres on TCP 5432 to the Internet. Rules permitting 0.0.0.0/0 or ::/0 to this port, or policies that open all ports publicly, are identified.
Risk
Exposing 5432 to the Internet enables credential stuffing and Postgres exploits, risking data disclosure (confidentiality), unauthorized changes (integrity), and service disruption via brute force or DoS (availability).
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432Recommendation
Apply least privilege on security groups: remove 0.0.0.0/0 and ::/0 for 5432, allow only trusted CIDRs or private peers. Prefer private access (VPC-only) via VPN, bastion, or proxy. Add defense in depth with SG references and network ACLs, and enforce TLS and strong authentication.
Remediation
CLI
aws ec2 revoke-security-group-ingress --group-id <SECURITY_GROUP_ID> --protocol tcp --port 5432 --cidr 0.0.0.0/0Terraform
# Security group with Postgres (5432) not exposed to the Internet
resource "aws_security_group" "<example_resource_name>" {
name = "<example_resource_name>"
vpc_id = "<example_resource_id>"
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"] # Critical: avoid 0.0.0.0/0 or ::/0 to prevent Internet exposure
}
}NativeIaC
# CloudFormation: restrict Postgres (5432) from the Internet
Resources:
<example_resource_name>:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "<example_resource_name>"
VpcId: "<example_resource_id>"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
CidrIp: 10.0.0.0/8 # Critical: not 0.0.0.0/0 or ::/0; limits access so 5432 is not open to the InternetOther
1In the AWS Console, go to VPC > Security Groups
2Select the affected security group
3Open the Inbound rules tab and click Edit inbound rules
4Locate any rule for PostgreSQL (port 5432) with Source 0.0.0.0/0 or ::/0
5Delete the rule or change Source to a specific CIDR or security group
6Click Save 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.ec2_securitygroup_allow_ingress_from_internet_to_all_ports import (
ec2_securitygroup_allow_ingress_from_internet_to_all_ports,
)
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_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432(Check):
def execute(self):
findings = []
check_ports = [5432]
for security_group_arn, security_group in ec2_client.security_groups.items():
# Check if ignoring flag is set and if the VPC and the SG is in use
if ec2_client.provider.scan_unused_services or (
security_group.vpc_id in vpc_client.vpcs
and vpc_client.vpcs[security_group.vpc_id].in_use
and len(security_group.network_interfaces) > 0
):
report = Check_Report_AWS(
metadata=self.metadata(), resource=security_group
)
report.resource_details = security_group.name
report.status = "PASS"
report.status_extended = f"Security group {security_group.name} ({security_group.id}) does not have Postgres port 5432 open to the Internet."
# only proceed if check "..._to_all_ports" did not run or did not FAIL to avoid to report open ports twice
if not ec2_client.is_failed_check(
ec2_securitygroup_allow_ingress_from_internet_to_all_ports.__name__,
security_group_arn,
):
# Loop through every security group's ingress rule and check it
for ingress_rule in security_group.ingress_rules:
if check_security_group(
ingress_rule, "tcp", check_ports, any_address=True
):
report.status = "FAIL"
report.status_extended = f"Security group {security_group.name} ({security_group.id}) has Postgres port 5432 open to the Internet."
break
else:
report.status_extended = f"Security group {security_group.name} ({security_group.id}) has all ports open to the Internet and therefore was not checked against the specific Postgres port 5432."
findings.append(report)
return findings