Back to Checks
Network ACL does not allow ingress from the Internet to TCP port 3389 (RDP)
ec2_networkacl_allow_ingress_tcp_port_3389
Service: ec2Severity: medium
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsEc2NetworkAcl
VPC network ACLs with inbound rules allowing RDP on TCP 3389 from 0.0.0.0/0 are identified.
Assessment focuses on subnet-level ACL entries that permit this traffic.
Risk
Internet-exposed RDP enables password spraying, brute force, and exploitation of RDP flaws to gain remote control. Allowing it at the subnet layer weakens defense in depth-a misconfigured security group or route can expose instances-leading to data exfiltration, privilege escalation, and ransomware, impacting confidentiality and integrity.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks ec2_networkacl_allow_ingress_tcp_port_3389Recommendation
Enforce least privilege: do not allow TCP 3389 from 0.0.0.0/0 in network ACLs.
- Restrict RDP to specific admin IP ranges
- Prefer bastion hosts or Session Manager over direct RDP
- Use private subnets and layer controls for defense in depth
Remediation
CLI
aws ec2 delete-network-acl-entry --network-acl-id <NETWORK_ACL_ID> --ingress --rule-number <RULE_NUMBER>Terraform
# Deny inbound RDP (TCP 3389) from the Internet on an existing NACL
resource "aws_network_acl_rule" "<example_resource_name>" {
network_acl_id = "<example_resource_id>"
rule_number = 1 # Critical: lower than any allow so deny takes precedence
egress = false # Ingress rule
protocol = "tcp"
rule_action = "deny" # Critical: block the traffic
cidr_block = "0.0.0.0/0" # Critical: Internet source
from_port = 3389 # Critical: RDP port
to_port = 3389
}NativeIaC
# CloudFormation: deny inbound RDP (TCP 3389) from the Internet on an existing NACL
Resources:
NetworkAclDenyRDP:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: <example_resource_id>
RuleNumber: 1 # Critical: ensure this deny is evaluated before any allow
Protocol: 6 # TCP
Egress: false # Ingress rule
RuleAction: deny # Critical: block the traffic
CidrBlock: 0.0.0.0/0 # Critical: Internet source
PortRange:
From: 3389 # Critical: RDP port
To: 3389Other
1In the AWS Console, go to VPC > Network ACLs and select the ACL used by the affected subnet(s)
2Open the Inbound rules tab
3Find any rule allowing TCP port 3389 (RDP) from 0.0.0.0/0 or ::/0
4Select that rule and click Delete, then Save
5If you must keep broad allows, instead click Edit inbound rules and add a new rule with a lower rule number that Denies TCP 3389 from 0.0.0.0/0, 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_3389(Check):
def execute(self):
findings = []
tcp_protocol = "6"
check_port = 3389
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 Microsoft RDP port 3389 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 Microsoft RDP port 3389 open to the Internet."
findings.append(report)
return findings