Skip to main content

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:DescribeNetworkAcls
  • ec2:ReplaceNetworkAclEntry
  • ec2:DeleteNetworkAclEntry
  • ec2:CreateNetworkAclEntry

AWS Console Method

  1. Open the VPC Console

  2. Navigate to Network ACLs

    • In the left sidebar, click Network ACLs
  3. Find the affected NACL

    • Locate the Network ACL flagged in the Prowler finding
    • Click on it to select it
  4. Review the Inbound Rules

    • Click the Inbound rules tab
    • Look for rules with these characteristics:
      • Source: 0.0.0.0/0
      • Port range: All or 0-65535
      • Protocol: All or -1
      • Action: Allow
  5. 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 traffic to specific protocols (like HTTP (80) or HTTPS (443))
    • Or change the Allow/Deny to Deny
    • Click Save changes
  6. 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) from 0.0.0.0/0 for web traffic
      • Example: SSH (22) from your corporate IP range only
    • 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:

  • CidrBlock is 0.0.0.0/0
  • Protocol is -1 (all protocols)
  • RuleAction is allow
  • Egress is false (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:

  1. 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/0 to all ports
  2. 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/0
  • Protocol: -1
  • RuleAction: allow

Re-run the Prowler check to confirm:

prowler aws -c ec2_networkacl_allow_ingress_any_port --region us-east-1

Additional Resources

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.