VPC default security group should restrict all traffic

Description

Configuring all VPC default security groups to restrict all traffic encourages least privilege security group development and mindful placement of AWS resources into security groups which in turn reduces the exposure of those resources.

Remediation Steps

AWS Console

  • Navigate to VPC.

  • Repeat the next steps for all your VPCs.

    • In the left navigation, select Security Groups.

    • Repeat the below steps for each default security group.

      • Select the default security group, click the Inbound Rules tab, and remove any inbound rules.

      • Click the Outbound Rules tab and remove any Outbound rules.

AWS CLI

  • List all default security groups and the rules associated with them. Output results to a text file for easier reference for the removal commands:

    • aws ec2 describe-security-groups --filters Name=group-name,Values='default' --query "SecurityGroups[*].{GroupName:GroupName,GroupID:GroupId,IPIngress:IpPermissions,IPEgress:IpPermissionsEgress}"

  • Use the output from the first command to get the information needed to remove each rule. Example of a command to remove an ingress rule on a security group:

    • aws ec2 revoke-security-group-ingress --group-id <value> --ip-permissions '[{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}]'

  • Use the output from the first command to get the information needed to remove each rule. Example of a command to remove an egress rule on a security group:

    • aws ec2 revoke-security-group-egress --group-id <value> --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 3389, "ToPort": 3389, "IpRanges": [{"CidrIp": "<value>"}]}]'

  • Bash script to remove all rules in the default region at once:

#!/bin/bash
set -o nounset -o errexit -o pipefail

# This is a script that removes ALL ingress and egress rules from security groups for the default VPCs. Check that `jq` is installed:

if ! (which jq >/dev/null 2>&1); then
    echo "jq must be installed" 1>&2
    exit 1
fi

# Get the description for the default security groups.  We store it in the `DESCRIPTION` variable so we don't need to re-fetch this.

DESCRIPTION="$(aws ec2 describe-security-groups \
    --filters Name=group-name,Values=default \
    --query 'SecurityGroups[*]' --output json)"

# Run through all security groups.

for group_id in $(echo "$DESCRIPTION" | jq -r '.[] | .GroupId'); do
    echo "Removing rules from security group $group_id..." 1>&2

# Get the description for this group specifically.

GROUP_DESCRIPTION="$(echo "$DESCRIPTION" | \
      jq "map(select(.GroupId == \"$group_id\")) | .[0]")"

# Run through ingress permissions.

  {
    IFS=$'\n'  # Make sure we only split on newlines.
    for ingress_rule in $(echo "$GROUP_DESCRIPTION" | \
            jq -c '.IpPermissions | .[]'); do
        echo "Removing ingress rule: $ingress_rule" 1>&2
        aws ec2 revoke-security-group-ingress \
            --group-id "$group_id" \
            --ip-permissions "$ingress_rule"
    done
    unset IFS
  }

# Run through egress permissions.

  {
    IFS=$'\n'  # Make sure we only split on newlines.
    for egress_rule in $(echo "$GROUP_DESCRIPTION" | \
            jq -c '.IpPermissionsEgress | .[]'); do
        echo "Removing egress rule: $egress_rule" 1>&2
        aws ec2 revoke-security-group-egress \
            --group-id "$group_id" \
            --ip-permissions "$egress_rule"
    done
    unset IFS
  }

done

CloudFormation

JSON

JSON Example Configuration
{
  "Type": "AWS::EC2::SecurityGroup",
  "Properties": {
    "VpcId": { "Ref": "Vpc01" }
  }
}

YAML

YAML Example Configuration
Type: AWS::EC2::SecurityGroup
Properties:
  VpcId: !Ref Vpc01

Terraform

Example Configuration

resource "aws_default_security_group" "default" {
  vpc_id = aws_vpc.myvpc.id
}