Network ACL Allows Ingress from 0.0.0.0/0 to Any Port
Overview
This check identifies Network Access Control Lists (NACLs) that have inbound rules allowing traffic from 0.0.0.0/0 (the entire internet) to all ports and protocols. NACLs act as stateless firewalls at the subnet boundary, controlling what traffic can enter or leave your subnets.
A rule allowing all ports from anywhere is extremely permissive and defeats the purpose of having a network firewall. This check ensures your NACLs follow the principle of least privilege by only allowing necessary traffic.
Risk
Allowing unrestricted internet access to all ports creates serious security risks:
- Port scanning exposure: Attackers can probe every port on your instances to discover running services
- Service exploitation: Any vulnerable service listening on any port is immediately accessible to attackers
- Data exfiltration: Malicious actors can establish connections to extract sensitive data
- Denial of service: Your resources become vulnerable to traffic floods and brute-force attacks
- Lateral movement: Once inside, attackers can move freely between resources in the subnet
This is a high severity finding because it removes one of your key network defense layers.
Remediation Steps
Prerequisites
You need:
- AWS Console access with permissions to modify VPC Network ACLs
- Knowledge of which ports your applications actually need to receive traffic on
Required IAM permissions
Your IAM user or role needs these permissions:
ec2:DescribeNetworkAclsec2:ReplaceNetworkAclEntryec2:DeleteNetworkAclEntryec2:CreateNetworkAclEntry
AWS Console Method
-
Open the VPC Console
- Go to VPC Console in us-east-1
-
Navigate to Network ACLs
- In the left sidebar, click Network ACLs
-
Find the affected NACL
- Locate the Network ACL flagged in the Prowler finding
- Click on it to select it
-
Review the Inbound Rules
- Click the Inbound rules tab
- Look for rules with these characteristics:
- Source:
0.0.0.0/0 - Port range:
Allor0-65535 - Protocol:
Allor-1 - Action:
Allow
- Source:
-
Choose your remediation approach:
Option A: Delete the overly permissive rule
- Click Edit inbound rules
- Click Remove next to the offending rule
- Click Save changes
- Add specific rules for only the ports you need (see step 6)
Option B: Replace the rule with a deny
- Click Edit inbound rules
- Change the Type from
All trafficto specific protocols (likeHTTP (80)orHTTPS (443)) - Or change the Allow/Deny to
Deny - Click Save changes
-
Add specific allow rules for required traffic
- Click Edit inbound rules
- Click Add new rule
- Configure only the specific ports your application needs:
- Example:
HTTPS (443)from0.0.0.0/0for web traffic - Example:
SSH (22)from your corporate IP range only
- Example:
- Click Save changes
Warning: Before removing or modifying rules, ensure you understand what traffic your applications require. Blocking needed traffic will cause service outages.
AWS CLI (optional)
Step 1: Identify the problematic rules
List all Network ACLs and their rules:
aws ec2 describe-network-acls \
--region us-east-1 \
--query 'NetworkAcls[*].{ID:NetworkAclId,VpcId:VpcId,Entries:Entries}' \
--output json
Look for inbound entries where:
CidrBlockis0.0.0.0/0Protocolis-1(all protocols)RuleActionisallowEgressisfalse(indicating inbound)
Step 2: Option A - Delete the permissive rule
Replace <nacl-id> and <rule-number> with your values:
aws ec2 delete-network-acl-entry \
--network-acl-id <nacl-id> \
--ingress \
--rule-number <rule-number> \
--region us-east-1
Step 2: Option B - Replace with a deny rule
Replace the allow rule with a deny rule:
aws ec2 replace-network-acl-entry \
--network-acl-id <nacl-id> \
--ingress \
--rule-number <rule-number> \
--protocol -1 \
--cidr-block 0.0.0.0/0 \
--rule-action deny \
--region us-east-1
Step 3: Add specific allow rules
Add rules for only the traffic you need. Example for HTTPS:
aws ec2 create-network-acl-entry \
--network-acl-id <nacl-id> \
--ingress \
--rule-number 100 \
--protocol 6 \
--port-range From=443,To=443 \
--cidr-block 0.0.0.0/0 \
--rule-action allow \
--region us-east-1
Example for SSH from a specific IP range:
aws ec2 create-network-acl-entry \
--network-acl-id <nacl-id> \
--ingress \
--rule-number 110 \
--protocol 6 \
--port-range From=22,To=22 \
--cidr-block 10.0.0.0/8 \
--rule-action allow \
--region us-east-1
CloudFormation (optional)
This template creates a Network ACL with secure, least-privilege rules:
AWSTemplateFormatVersion: '2010-09-09'
Description: Secure Network ACL with restricted ingress rules
Parameters:
VpcId:
Type: AWS::EC2::VPC::Id
Description: VPC ID where the Network ACL will be created
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Subnet ID to associate with this Network ACL
TrustedCidrBlock:
Type: String
Description: CIDR block for trusted administrative access (e.g., corporate network)
Default: 10.0.0.0/8
Resources:
SecureNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VpcId
Tags:
- Key: Name
Value: secure-nacl
# Allow HTTPS inbound from anywhere (for web servers)
InboundHttpsRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 100
Protocol: 6
RuleAction: allow
CidrBlock: 0.0.0.0/0
PortRange:
From: 443
To: 443
# Allow HTTP inbound from anywhere (for web servers, redirect to HTTPS)
InboundHttpRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 110
Protocol: 6
RuleAction: allow
CidrBlock: 0.0.0.0/0
PortRange:
From: 80
To: 80
# Allow SSH from trusted network only
InboundSshRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 120
Protocol: 6
RuleAction: allow
CidrBlock: !Ref TrustedCidrBlock
PortRange:
From: 22
To: 22
# Allow ephemeral ports for return traffic
InboundEphemeralRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 140
Protocol: 6
RuleAction: allow
CidrBlock: 0.0.0.0/0
PortRange:
From: 1024
To: 65535
# Deny all other inbound traffic (explicit deny)
InboundDenyAllRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 200
Protocol: -1
RuleAction: deny
CidrBlock: 0.0.0.0/0
# Allow all outbound traffic
OutboundAllRule:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref SecureNetworkAcl
RuleNumber: 100
Protocol: -1
Egress: true
RuleAction: allow
CidrBlock: 0.0.0.0/0
# Associate NACL with subnet
SubnetNetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref SubnetId
NetworkAclId: !Ref SecureNetworkAcl
Outputs:
NetworkAclId:
Description: ID of the secure Network ACL
Value: !Ref SecureNetworkAcl
Deploy with:
aws cloudformation deploy \
--template-file secure-nacl.yaml \
--stack-name secure-network-acl \
--parameter-overrides \
VpcId=vpc-12345678 \
SubnetId=subnet-12345678 \
TrustedCidrBlock=10.0.0.0/8 \
--region us-east-1
Terraform (optional)
variable "vpc_id" {
description = "VPC ID where the Network ACL will be created"
type = string
}
variable "subnet_ids" {
description = "List of subnet IDs to associate with this Network ACL"
type = list(string)
}
variable "trusted_cidr_block" {
description = "CIDR block for trusted administrative access"
type = string
default = "10.0.0.0/8"
}
resource "aws_network_acl" "secure" {
vpc_id = var.vpc_id
subnet_ids = var.subnet_ids
tags = {
Name = "secure-nacl"
}
}
# Allow HTTPS inbound from anywhere
resource "aws_network_acl_rule" "inbound_https" {
network_acl_id = aws_network_acl.secure.id
rule_number = 100
egress = false
protocol = "tcp"
rule_action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 443
to_port = 443
}
# Allow HTTP inbound from anywhere
resource "aws_network_acl_rule" "inbound_http" {
network_acl_id = aws_network_acl.secure.id
rule_number = 110
egress = false
protocol = "tcp"
rule_action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 80
to_port = 80
}
# Allow SSH from trusted network only
resource "aws_network_acl_rule" "inbound_ssh" {
network_acl_id = aws_network_acl.secure.id
rule_number = 120
egress = false
protocol = "tcp"
rule_action = "allow"
cidr_block = var.trusted_cidr_block
from_port = 22
to_port = 22
}
# Allow ephemeral ports for return traffic
resource "aws_network_acl_rule" "inbound_ephemeral" {
network_acl_id = aws_network_acl.secure.id
rule_number = 140
egress = false
protocol = "tcp"
rule_action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 1024
to_port = 65535
}
# Explicit deny all other inbound traffic
resource "aws_network_acl_rule" "inbound_deny_all" {
network_acl_id = aws_network_acl.secure.id
rule_number = 200
egress = false
protocol = "-1"
rule_action = "deny"
cidr_block = "0.0.0.0/0"
}
# Allow all outbound traffic
resource "aws_network_acl_rule" "outbound_all" {
network_acl_id = aws_network_acl.secure.id
rule_number = 100
egress = true
protocol = "-1"
rule_action = "allow"
cidr_block = "0.0.0.0/0"
}
output "network_acl_id" {
description = "ID of the secure Network ACL"
value = aws_network_acl.secure.id
}
Deploy with:
terraform init
terraform plan -var="vpc_id=vpc-12345678" -var='subnet_ids=["subnet-12345678"]'
terraform apply -var="vpc_id=vpc-12345678" -var='subnet_ids=["subnet-12345678"]'
Verification
After remediation, verify the rules have been corrected:
-
In the AWS Console:
- Go to VPC > Network ACLs
- Select the remediated NACL
- Click the Inbound rules tab
- Confirm there are no rules allowing
0.0.0.0/0to all ports
-
Test your applications:
- Verify that legitimate traffic still flows correctly
- Test that blocked ports are no longer accessible from the internet
CLI verification commands
Check the NACL rules:
aws ec2 describe-network-acls \
--network-acl-ids <nacl-id> \
--region us-east-1 \
--query 'NetworkAcls[0].Entries[?Egress==`false`]'
The output should not show any entries with:
CidrBlock: 0.0.0.0/0Protocol: -1RuleAction: allow
Re-run the Prowler check to confirm:
prowler aws -c ec2_networkacl_allow_ingress_any_port --region us-east-1
Additional Resources
- AWS Documentation: Network ACLs
- AWS Documentation: Control Traffic to Subnets Using Network ACLs
- AWS Documentation: Recommended Network ACL Rules for Your VPC
- AWS Security Best Practices: Network Security
Notes
- Defense in depth: NACLs are just one layer of network security. Always use security groups as well for granular instance-level protection.
- Stateless nature: NACLs are stateless, meaning you need to allow return traffic explicitly. The ephemeral port rule (1024-65535) in the examples handles this for TCP connections.
- Rule evaluation order: NACL rules are evaluated in order by rule number (lowest first). The first matching rule is applied. Plan your rule numbers accordingly.
- Default NACL: Every VPC has a default NACL that allows all inbound and outbound traffic. Consider creating custom NACLs with explicit rules instead.
- Service disruption risk: Modifying NACL rules takes effect immediately. Test changes in non-production environments first when possible.
- IPv6 consideration: If your VPC uses IPv6, also check for rules allowing
::/0(all IPv6 addresses) and apply the same restrictions.