Skip to main content
emnode / learn
Compliance High severity

AWS Security Hub · EC2

EC2.18: Security groups open ports beyond what is authorised

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub EC2.18 check?

EC2.18 fails when a security group opens any port to 0.0.0.0/0 (or ::/0) that is not on a customer-configured allow-list. By default the authorised list is just 80 and 443 — the stricter inverse of EC2.19, which only checks a fixed list of known-dangerous ports.

Why does EC2.18 matter?

EC2.19 asks "is this port on the known-bad list?"; EC2.18 asks "is this port explicitly allowed?" That flip catches the long tail of app-tier services accidentally exposed to the internet — Redis on 6379, Elasticsearch on 9200, RabbitMQ on 5672, gRPC on 50051, debug ports on 9229 — none of which are on EC2.19's list but none of which belong on the public internet.

How do I fix EC2.18?

  1. Audit every ingress rule with a 0.0.0.0/0 or ::/0 source and join it against your authorised-port list.
  2. Replace each over-broad rule with the smallest scope that works — the VPC CIDR, a peer CIDR, or the load balancer's security group reference.
  3. For ports that genuinely need to be public, terminate on an ALB or NLB rather than exposing the instance directly.
  4. Update the authorised-port parameter deliberately via UpdateSecurityControl only after a documented review, never reactively.

Remediation script · bash

# Revoke an over-open admin rule, covering both IPv4 and IPv6 in one call.
aws ec2 revoke-security-group-ingress --group-id sg-0a1b2c3d \
  --ip-permissions 'IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges=[{CidrIp=0.0.0.0/0}],Ipv6Ranges=[{CidrIpv6=::/0}]'

# Where access is genuinely needed, re-add it scoped to a source security group, not a CIDR.
aws ec2 authorize-security-group-ingress --group-id sg-0a1b2c3d \
  --ip-permissions 'IpProtocol=tcp,FromPort=6379,ToPort=6379,UserIdGroupPairs=[{GroupId=sg-0app1234,Description=app-tier}]'

# Strip a default security group to empty by feeding its current rules back into revoke.
INGRESS=$(aws ec2 describe-security-groups --group-ids sg-0default01 \
  --query 'SecurityGroups[0].IpPermissions')
[ "$INGRESS" != "[]" ] && aws ec2 revoke-security-group-ingress \
  --group-id sg-0default01 --ip-permissions "$INGRESS"

Full walkthrough (console steps, edge cases and verification) in the lesson Harden security groups and restrict ingress.

Is EC2.18 a false positive?

The port comparison is exact, not range-tolerant: a rule for 80-8080 fails because the range includes ports outside the allow-list, even though it covers 80. The fix is almost always to narrow the rule's range, not to widen the authorised list.

Part of the learning path Lock down access
  • EC2.1 An EBS snapshot is publicly restorable by any account
  • EC2.2 Default security groups still allow traffic
  • EC2.3 Attached EBS volumes are not encrypted at rest
  • EC2.4 Long-stopped instances are abandoned attack surface
  • EC2.6 No VPC flow logs, so there is no network audit trail
  • EC2.7 New EBS volumes are not encrypted by default
  • EC2.8 IMDSv1 lets an SSRF steal instance credentials
  • EC2.9 Instances are directly reachable on public IPv4
  • EC2.10 EC2 API traffic leaves the VPC over the internet
  • EC2.13 SSH (port 22) is open to the entire internet
  • EC2.14 RDP (port 3389) is open to the entire internet
  • EC2.15 Subnets auto-assign public IPs to new instances