Default Security Groups Should Not Allow Unrestricted
More Info:
Your AWS EC2 default security groups should restrict all inbound public traffic in order to enforce AWS users (EC2 administrators, resource managers, etc) to create custom security groups that exercise the rule of least privilege instead of using the default security groups.
Risk Level
Low
Address
Security
Compliance Standards
CISAWS, CBP, NIST, SOC2, PCIDSS, GDPR, AWSWAF, NISTCSF, FedRAMP
Remediation
How to ensure default Security Group does not allow unrestricted inbound access
Using Console
To remediate the misconfiguration "Default Security Group Should Not Allow Unrestricted Public Traffic" for AWS using the AWS console, follow the steps below:
-
Log in to the AWS Management Console.
-
Navigate to the EC2 service.
-
In the left-hand menu, click on "Security Groups".
-
Select the default security group.
-
In the "Inbound Rules" tab, remove any rules that allow unrestricted public traffic (i.e. 0.0.0.0/0).
-
Add specific rules for the required ports and protocols to allow traffic only from authorized sources.
-
Review and save the changes.
By following these steps, you will remediate the misconfiguration and ensure that the default security group does not allow unrestricted public traffic.
Using CLI
To remediate the misconfiguration "Default Security Group Should Not Allow Unrestricted Public Traffic" for AWS using AWS CLI, follow the below steps:
-
Open the AWS CLI on your local machine.
-
Run the following command to get the ID of the default security group in your AWS account:
aws ec2 describe-security-groups --filters Name=group-name,Values=default --query 'SecurityGroups[*].GroupId' --output text -
Run the following command to update the inbound rules of the default security group to allow only necessary traffic:
aws ec2 revoke-security-group-ingress --group-id <security-group-id> --protocol all --port all --cidr 0.0.0.0/0This command will remove all the inbound rules that allow unrestricted public traffic.
-
Now, add the necessary inbound rules to the default security group using the following command:
aws ec2 authorize-security-group-ingress --group-id <security-group-id> --protocol tcp --port <port-number> --cidr <ip-address>Replace
<port-number>with the port number you want to allow traffic for and<ip-address>with the IP address range you want to allow traffic from. -
Repeat step 4 for all the necessary inbound rules.
-
Verify the updated inbound rules of the default security group using the following command:
aws ec2 describe-security-groups --group-ids <security-group-id>This command will display the updated inbound rules for the default security group.
By following the above steps, you can remediate the misconfiguration "Default Security Group Should Not Allow Unrestricted Public Traffic" for AWS using AWS CLI.
Using Python
To remediate the misconfiguration of default security group allowing unrestricted public traffic in AWS using Python, you can follow these steps:
- Import the necessary AWS SDK libraries and modules in Python.
import boto3
- Create a connection to the AWS EC2 service using the boto3 library.
ec2 = boto3.client('ec2')
- Get the default security group ID using the describe_security_groups() method.
response = ec2.describe_security_groups(GroupNames=['default'])
sg_id = response['SecurityGroups'][0]['GroupId']
- Revoke the ingress rules that allow unrestricted public traffic using the revoke_security_group_ingress() method.
response = ec2.revoke_security_group_ingress(
GroupId=sg_id,
IpPermissions=[
{
'IpProtocol': '-1',
'IpRanges': [{'CidrIp': '0.0.0.0/0'}]
}
]
)
- Confirm that the ingress rules have been revoked by describing the security group again.
response = ec2.describe_security_groups(GroupNames=['default'])
print(response)
This should remediate the misconfiguration of default security group allowing unrestricted public traffic in AWS using Python.
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step instructions to remove unrestricted inbound access from default Security Groups in AWS using the AWS Management Console.
1. Identify default Security Groups
- Sign in to the AWS Management Console.
- Go to EC2:
- In the services search bar, type EC2 and click EC2.
- In the left navigation pane, under Network & Security, click Security Groups.
- In the Security Groups list:
- Add the column Group Name and VPC ID if not visible.
- Default Security Groups typically have Group Name like
defaultand Description: “default VPC security group”.
- You can also filter:
- In the search bar, type:
group-name = default
This will show one default Security Group per VPC.
- In the search bar, type:
2. Check for unrestricted inbound rules
For each default Security Group:
- Select the Security Group.
- At the bottom, open the Inbound rules tab.
- Look for any rules that:
- Have Type =
All traffic,All TCP,All UDP, or specific ports likeSSH (22),RDP (3389),HTTP (80),HTTPS (443)etc. - And Source =
0.0.0.0/0(IPv4) and/or::/0(IPv6).
These are “unrestricted inbound” rules.
- Have Type =
3. Remove or restrict inbound rules on the default Security Group
You cannot delete the default Security Group, but you can change its rules.
- With the default Security Group selected, click Edit inbound rules.
- For each rule that has Source
0.0.0.0/0or::/0:- Either:
- Delete the rule (click the trash icon), or
- Change Source to something more restrictive, e.g.:
- A specific CIDR like
10.0.0.0/16(your internal network), - Or a specific IP such as
203.0.113.10/32(admin workstation).
- A specific CIDR like
- Either:
- If you do not need any inbound traffic via the default SG:
- Remove all inbound rules, leaving the inbound rules list empty.
- Click Save rules.
Repeat this for the default Security Group in every VPC in your account/region.
4. Ensure new resources don’t rely on the default SG for inbound access
- When launching new EC2 instances:
- In Step: Configure Security Group (or equivalent in the console wizard), do not select the default Security Group for publicly exposed services.
- Instead, create/choose a dedicated SG with only the specific ports and IP ranges needed.
- For existing instances that rely on the default SG for inbound access:
- Create a new Security Group with least-privilege rules.
- Attach the new SG to the instance:
- Select the instance → Actions → Security → Change security groups.
- Add the new SG and (optionally) remove the default SG.
- Click Apply.
5. (Optional) Check outbound rules on default SG
Best practice is to also restrict outbound where needed:
- Select the default Security Group.
- Open Outbound rules.
- Click Edit outbound rules.
- Remove or tighten any
0.0.0.0/0or::/0rules if your policy requires restricted egress. - Click Save rules.
By completing the above steps for each default Security Group in each VPC, you will have removed unrestricted inbound access while keeping the default SG itself (which cannot be deleted).
Using CLI
Below are concise, step‑by‑step AWS CLI instructions to lock down default Security Groups so they don’t allow unrestricted (0.0.0.0/0 or ::/0) inbound access.
1. Identify all default Security Groups
aws ec2 describe-security-groups \
--filters Name=group-name,Values=default \
--query 'SecurityGroups[*].{GroupId:GroupId,GroupName:GroupName,VpcId:VpcId}' \
--output table
Keep the GroupId values; you’ll need them for the next steps.
2. Review current inbound rules for a specific default Security Group
Replace <sg-id> with the Security Group ID:
aws ec2 describe-security-groups \
--group-ids <sg-id> \
--query 'SecurityGroups[0].IpPermissions'
Look for any rules where:
IpRanges[].CidrIpis0.0.0.0/0Ipv6Ranges[].CidrIpv6is::/0
3. Revoke unrestricted IPv4 inbound rules
This example revokes all IPv4 inbound rules from the default SG that are open to 0.0.0.0/0.
First get those rules in a form the CLI can accept:
aws ec2 describe-security-groups \
--group-ids <sg-id> \
--query 'SecurityGroups[0].IpPermissions[?contains(IpRanges[].CidrIp, `0.0.0.0/0`)]' \
> ipv4-open-rules.json
If ipv4-open-rules.json is not empty, run:
aws ec2 revoke-security-group-ingress \
--group-id <sg-id> \
--ip-permissions file://ipv4-open-rules.json
4. Revoke unrestricted IPv6 inbound rules
Similarly for IPv6 (::/0):
aws ec2 describe-security-groups \
--group-ids <sg-id> \
--query 'SecurityGroups[0].IpPermissions[?contains(Ipv6Ranges[].CidrIpv6, `::/0`)]' \
> ipv6-open-rules.json
If ipv6-open-rules.json is not empty:
aws ec2 revoke-security-group-ingress \
--group-id <sg-id> \
--ip-permissions file://ipv6-open-rules.json
5. Repeat for all default Security Groups
Loop over all default SGs in a shell (bash example):
for SG in $(aws ec2 describe-security-groups \
--filters Name=group-name,Values=default \
--query 'SecurityGroups[].GroupId' \
--output text); do
echo "Processing $SG"
aws ec2 describe-security-groups \
--group-ids $SG \
--query 'SecurityGroups[0].IpPermissions[?contains(IpRanges[].CidrIp, `0.0.0.0/0`)]' \
> ipv4-open-rules.json
if [ -s ipv4-open-rules.json ]; then
aws ec2 revoke-security-group-ingress \
--group-id $SG \
--ip-permissions file://ipv4-open-rules.json
fi
aws ec2 describe-security-groups \
--group-ids $SG \
--query 'SecurityGroups[0].IpPermissions[?contains(Ipv6Ranges[].CidrIpv6, `::/0`)]' \
> ipv6-open-rules.json
if [ -s ipv6-open-rules.json ]; then
aws ec2 revoke-security-group-ingress \
--group-id $SG \
--ip-permissions file://ipv6-open-rules.json
fi
done
6. (Optional) Add restricted inbound rules instead
Example: allow SSH only from a corporate CIDR (replace 203.0.113.0/24):
aws ec2 authorize-security-group-ingress \
--group-id <sg-id> \
--ip-permissions '[
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"IpRanges": [{"CidrIp": "203.0.113.0/24","Description": "SSH from corp"}]
}
]'
This ensures the default Security Groups no longer allow unrestricted inbound access.
Using Python
Below is a step‑by‑step approach plus a ready‑to‑run Python (boto3) script that:
- Finds all default security groups in all regions.
- Removes any inbound rules that allow unrestricted access (0.0.0.0/0 or ::/0).
Prerequisites
- AWS credentials configured (e.g.,
~/.aws/credentialsor environment variables). - Python 3.x
boto3installed:pip install boto3
Remediation Logic
- Enumerate all AWS regions.
- For each region:
- Get all security groups where
GroupName == 'default'. - Inspect
IpPermissions(inbound rules). - For each permission, check if any of:
IpRangeshasCidrIp == '0.0.0.0/0'Ipv6RangeshasCidrIpv6 == '::/0'
- Build a permission structure that includes only the unrestricted ranges to be removed.
- Call
revoke_security_group_ingresswith those specific ranges.
- Get all security groups where
Python Script (boto3)
import boto3
from botocore.exceptions import ClientError
def get_all_regions():
ec2 = boto3.client('ec2')
regions = ec2.describe_regions(AllRegions=True)['Regions']
return [r['RegionName'] for r in regions if r['OptInStatus'] in ('opt-in-not-required', 'opted-in')]
def remove_unrestricted_inbound_from_default_sg(region):
ec2 = boto3.client('ec2', region_name=region)
print(f"\n[Region: {region}]")
try:
# Get all default security groups
response = ec2.describe_security_groups(
Filters=[
{'Name': 'group-name', 'Values': ['default']}
]
)
sgs = response['SecurityGroups']
if not sgs:
print(" No default security groups found.")
return
for sg in sgs:
group_id = sg['GroupId']
group_name = sg.get('GroupName', '')
print(f" Checking SG: {group_id} ({group_name})")
ip_permissions_to_revoke = []
for perm in sg.get('IpPermissions', []):
new_perm = {
'IpProtocol': perm['IpProtocol'],
'FromPort': perm.get('FromPort'),
'ToPort': perm.get('ToPort'),
'IpRanges': [],
'Ipv6Ranges': [],
'UserIdGroupPairs': [],
'PrefixListIds': []
}
# Only pick the "unrestricted" IPv4 ranges
for r in perm.get('IpRanges', []):
if r.get('CidrIp') == '0.0.0.0/0':
new_perm['IpRanges'].append(r)
# Only pick the "unrestricted" IPv6 ranges
for r in perm.get('Ipv6Ranges', []):
if r.get('CidrIpv6') == '::/0':
new_perm['Ipv6Ranges'].append(r)
# If this permission has any unrestricted ranges, queue it to revoke
if new_perm['IpRanges'] or new_perm['Ipv6Ranges']:
# Clean empty fields because boto3 can complain about them
new_perm = {k: v for k, v in new_perm.items() if v not in (None, [], '')}
ip_permissions_to_revoke.append(new_perm)
if ip_permissions_to_revoke:
print(f" Revoking unrestricted ingress from SG {group_id} ...")
try:
ec2.revoke_security_group_ingress(
GroupId=group_id,
IpPermissions=ip_permissions_to_revoke
)
print(" Done.")
except ClientError as e:
print(f" ERROR revoking rules for {group_id}: {e}")
else:
print(" No unrestricted inbound rules found.")
except ClientError as e:
print(f" ERROR describing SGs in {region}: {e}")
def main():
regions = get_all_regions()
for region in regions:
remove_unrestricted_inbound_from_default_sg(region)
if __name__ == "__main__":
main()
How to Run
- Save as
fix_default_sg_unrestricted.py. - Run:
python fix_default_sg_unrestricted.py
- Verify by checking default security groups in the AWS Console or via:
aws ec2 describe-security-groups --group-names default --region <region>
This script only removes unrestricted inbound from default security groups and leaves other (more specific) rules intact.
Using Terraform
resource "aws_default_security_group" "default_sg" {
# Substitute YOUR_VPC_ID with the ID of the VPC whose default SG you are remediating
vpc_id = "YOUR_VPC_ID"
# REMOVE all ingress rules to avoid unrestricted inbound access
# If specific inbound access is required, define only those ports/CIDR blocks explicitly.
ingress = []
# Example: allow all outbound traffic (adjust if your policy is stricter)
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = "default-security-group-YOUR_VPC_ID"
}
}
This configuration manages the existing default security group in-place (no replacement of the SG itself; Terraform will just remove any existing unrestricted ingress rules).
Verification: terraform plan should show all existing ingress rules on the default security group being removed (or replaced with the empty set) and only the specified egress rule(s) present.