Back to Checks
aws

Network ACL does not allow ingress from the Internet to TCP port 22 (SSH)

ec2_networkacl_allow_ingress_tcp_port_22
Service: ec2Severity: medium
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsEc2NetworkAcl

VPC network ACLs are evaluated for inbound rules that permit 0.0.0.0/0 to access SSH on TCP 22 at the subnet boundary.

Risk

An ACL allowing Internet-wide SSH erodes defense in depth. Systems reachable on TCP 22 face brute-force, credential stuffing, reconnaissance, and SSH exploit attempts.

Changes to routes or security groups can create direct exposure, enabling unauthorized access and lateral movement, undermining confidentiality and integrity.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks ec2_networkacl_allow_ingress_tcp_port_22

Recommendation

Apply least privilege at the subnet layer:

  • Do not allow 0.0.0.0/0 to TCP 22
  • Restrict SSH to trusted sources, or avoid direct SSH via Session Manager or a bastion behind VPN

Pair tight security groups with periodic rule reviews and change control to maintain defense in depth.

Remediation

CLI

aws ec2 replace-network-acl-entry --network-acl-id <NETWORK_ACL_ID> --ingress --rule-number <RULE_NUMBER> --protocol 6 --rule-action deny --cidr-block 0.0.0.0/0 --port-range From=22,To=22

Terraform

# Deny SSH (22) from Internet on the NACL
resource "aws_network_acl_rule" "<example_resource_name>" {
  network_acl_id = "<example_resource_id>"
  rule_number    = 1
  egress         = false
  protocol       = "tcp"
  rule_action    = "deny"          # Critical: blocks SSH ingress
  cidr_block     = "0.0.0.0/0"     # Critical: Internet sources
  from_port      = 22               # Critical: SSH port
  to_port        = 22
}

NativeIaC

# CloudFormation: Deny SSH (22) from Internet on the NACL
Resources:
  <example_resource_name>:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      NetworkAclId: <example_resource_id>
      RuleNumber: 1
      Protocol: 6
      RuleAction: deny   # Critical: blocks the traffic instead of allowing it
      Egress: false
      CidrBlock: 0.0.0.0/0  # Critical: matches Internet sources
      PortRange:
        From: 22           # Critical: SSH port
        To: 22

Other

1In AWS Console, go to VPC > Network ACLs
2Select <example_resource_name> and open the Inbound rules tab
3Delete any rule that ALLOWS TCP port 22 from 0.0.0.0/0 or ::/0
4Save changes
5If you cannot delete it, edit the rule and set Action to Deny for TCP port 22 with source 0.0.0.0/0 (and ::/0 if present), then save

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.network_acls import check_network_acl


class ec2_networkacl_allow_ingress_tcp_port_22(Check):
    def execute(self):
        findings = []
        tcp_protocol = "6"
        check_port = 22
        for arn, network_acl in ec2_client.network_acls.items():
            if (
                ec2_client.provider.scan_unused_services
                or network_acl.region in ec2_client.regions_with_sgs
            ):
                report = Check_Report_AWS(
                    metadata=self.metadata(), resource=network_acl
                )
                # If some entry allows it, that ACL is not securely configured
                if check_network_acl(network_acl.entries, tcp_protocol, check_port):
                    report.status = "FAIL"
                    report.status_extended = f"Network ACL {network_acl.name if network_acl.name else network_acl.id} has SSH port 22 open to the Internet."
                    findings.append(report)
                else:
                    report.status = "PASS"
                    report.status_extended = f"Network ACL {network_acl.name if network_acl.name else network_acl.id} does not have SSH port 22 open to the Internet."
                    findings.append(report)

        return findings