HackBlue

Tools · Cloud security · 13 / 24

Find AWS security groups open to the internet on SSH, RDP, and databases

Query security groups for 0.0.0.0/0 and ::/0 rules on sensitive ports, see which instances use them, and replace them with Session Manager or scoped rules.

9 min read · practice only with authorization

The most common network finding

A security group rule allowing 0.0.0.0/0 to port 22 or 3389 exposes SSH or RDP to the whole internet, where automated guessing starts within minutes. Database ports such as 3306, 5432, 1433, 6379, 9200, and 27017 open to the world are worse, because many databases ship with weak or no authentication.

IPv6 rules matter too: ::/0 is the IPv6 equivalent and is easy to miss.

Query every group

describe-security-groups with filters finds rules with 0.0.0.0/0. jq makes it easy to print the group, port range, and description. Then find which network interfaces use each group to see whether anything is actually exposed.

Run it in every region you use, and in the ones you do not.

Snippet
for r in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
  aws ec2 describe-security-groups --region $r --output json | jq -r --arg r $r '.SecurityGroups[] | .GroupId as $g | .IpPermissions[] |
    select((.IpRanges[]?.CidrIp=="0.0.0.0/0") or (.Ipv6Ranges[]?.CidrIpv6=="::/0")) |
    select((.FromPort // 0) <= 22 and (.ToPort // 65535) >= 22 or (.FromPort // 0) <= 3389 and (.ToPort // 65535) >= 3389 or .IpProtocol=="-1") |
    [$r, $g, .IpProtocol, (.FromPort|tostring), (.ToPort|tostring)] | @tsv'
done
aws ec2 describe-network-interfaces --filters Name=group-id,Values=sg-0abc123 --query 'NetworkInterfaces[].{eni:NetworkInterfaceId,instance:Attachment.InstanceId,public:Association.PublicIp}'

Lab: replace SSH with Session Manager

Launch a sandbox instance with the SSM agent, an instance profile with AmazonSSMManagedInstanceCore, and no inbound rules at all. Connect with aws ssm start-session. You have a shell without any open port, and sessions can be logged to CloudWatch or S3.

For cases that truly need inbound access, scope the rule to a specific address or a prefix list for your office or VPN, and add a description with the owner and ticket.

Snippet
aws ssm start-session --target i-0123456789abcdef0
aws ec2 revoke-security-group-ingress --group-id sg-0abc123 --protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id sg-0abc123 --ip-permissions 'IpProtocol=tcp,FromPort=22,ToPort=22,PrefixListIds=[{PrefixListId=pl-0vpn123,Description="VPN only, ticket SEC-142"}]'

Keep it fixed

AWS Config’s restricted-ssh and restricted-common-ports managed rules check continuously. Security Hub’s foundational best practices include the same controls. Alert on AuthorizeSecurityGroupIngress events with 0.0.0.0/0 in CloudTrail.

Unused security groups are clutter that hides risk. Delete groups not attached to any interface after confirming with owners.

Diagram

Open SSH versus Session Manager

How administrators reach the instance.

0.0.0.0/0 on port 22

Exposure. Entire internet can attempt logins.

Credentials. SSH keys spread across laptops.

Logging. Only what the host records.

Session Manager

Exposure. No inbound port.

Credentials. IAM with MFA.

Logging. Sessions logged centrally.

Check yourself

1. Which CIDR is the IPv6 equivalent of 0.0.0.0/0?

2. How can admins get a shell without any inbound rule?

3. Which managed AWS Config rule flags SSH open to the world?