April 15, 2019

Finding all Vulnerable Security groups in AWS using golang

Security is very important for any AWS infrastructure. Security groups are essential component for AWS security. Security group acts a virtual firewall for all instances and services (RDS, Elasticache etc.). Security groups provides ingress and egress permissions for an instance. Generally public access is provided to HTTP (80) and HTTPS (443) ports. Additionally SMTP ports 25, 465, 587 can also have public access. Any other ports should be restricted to internal security groups or internal IP addresses.

Script in golang

New let us look at the script to get all vulnerable security groups. As discussed, we need to find all security groups which has ports other than 80, 443, 25, 465 and 587 exposed to public. Let us use aws-sdk-go to get all the vulnerable security groups:


package main

import (
	"log"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ec2"
)

func main() {
	svc := ec2.New(session.New())
	var maxResults int64
	maxResults = 500
	var nextToken string
	for {
		descSGInput := &ec2.DescribeSecurityGroupsInput{
			MaxResults: aws.Int64(maxResults),
		}

		if nextToken != "" {
			descSGInput.NextToken = aws.String(nextToken)
		}

		descSGOut, err := svc.DescribeSecurityGroups(descSGInput)
		if err != nil {
			log.Println("Unable to get security groups. Err:", err)
			os.Exit(1)
		}

		for _, sg := range descSGOut.SecurityGroups {
			for _, ingress := range sg.IpPermissions {
				if (ingress.FromPort != nil && *ingress.FromPort == 80 && *ingress.ToPort == 80) ||
					(ingress.ToPort != nil && *ingress.FromPort == 443 && *ingress.ToPort == 443) ||
					(ingress.ToPort != nil && *ingress.FromPort == 25 && *ingress.ToPort == 25) ||
					(ingress.ToPort != nil && *ingress.FromPort == 465 && *ingress.ToPort == 465) ||
					(ingress.ToPort != nil && *ingress.FromPort == 587 && *ingress.ToPort == 587) {
					continue
				}

				if len(ingress.IpRanges) > 0 {
					for _, ipRange := range ingress.IpRanges {
						if *ipRange.CidrIp == "0.0.0.0/0" {
							var fromPort, toPort int64
							if ingress.FromPort != nil {
								fromPort = *ingress.FromPort
							}

							if ingress.ToPort != nil {
								toPort = *ingress.ToPort
							}

							log.Printf(`Unsafe security group. ID: %s , Name: %s, FromPort: %d, ToPort: %d`,
								*sg.GroupId, *sg.GroupName,
								fromPort, toPort)
						}
					}
				}
			}
		}

		if descSGOut.NextToken != nil {
			nextToken = *descSGOut.NextToken
		} else {
			break
		}
	}
}