# EC2 Instance and Security Group Enumeration

> Enumerate AWS EC2 instances and security groups using CLI and SDK techniques to map attack surface, expose misconfigurations, and identify lateral movement opportunities.

- **URL:** https://hackindex.io/platforms/aws/enumeration/ec2/ec2-instance-and-security-group-enumeration
- **Path:** AWS > Enumeration > EC2
- **Up:** [EC2](https://hackindex.io/platforms/aws/enumeration/ec2.md)
- **Published:** 2026-05-24
- **Updated:** 2026-05-24

EC2 enumeration maps running compute, attached roles, network exposure, and snapshot history. Security groups define what traffic is allowed: misconfigurations here directly translate to exploitation paths.

- Instances with attached IAM roles that have overly broad permissions
- Security groups allowing `0.0.0.0/0` on management ports (SSH, RDP, WinRM)
- User data scripts containing hardcoded credentials or bootstrap secrets
- Public EBS snapshots leaking filesystem contents to any AWS account
- Instances running IMDSv1 (vulnerable to SSRF-based credential theft)

## Instances

**List all instances**

```bash
aws ec2 describe-instances --profile $PROFILE --region $REGION --query 'Reservations[*].Instances[*].{ID:InstanceId,Type:InstanceType,State:State.Name,IP:PublicIpAddress,PrivateIP:PrivateIpAddress,IAMRole:IamInstanceProfile.Arn,AZ:Placement.AvailabilityZone}' --output table
```

**Check user data for secrets**

```bash
aws ec2 describe-instance-attribute --instance-id $INSTANCE_ID --attribute userData --profile $PROFILE --region $REGION | jq -r '.UserData.Value' | base64 -d
```

## Security Groups

**Find groups open to internet**

```bash
aws ec2 describe-security-groups --profile $PROFILE --region $REGION --query "SecurityGroups[?IpPermissions[?IpRanges[?CidrIp=='0.0.0.0/0']]].{ID:GroupId,Name:GroupName,Rules:IpPermissions}" --output json
```

High-value findings: ports 22, 3389, 5985, 5986, 3306, 5432, 6379, 27017 open to `0.0.0.0/0`.

## EBS Snapshots

**Check for public snapshots**

```bash
aws ec2 describe-snapshots --owner-ids self --profile $PROFILE --region $REGION --query 'Snapshots[*].SnapshotId' --output text | xargs -I {} aws ec2 describe-snapshot-attribute --snapshot-id {} --attribute createVolumePermission --profile $PROFILE --region $REGION 2>/dev/null | grep -v '"Groups": \[\]'
```

## Instance Metadata Service Version

```bash
aws ec2 describe-instances --profile $PROFILE --region $REGION --query 'Reservations[*].Instances[*].{ID:InstanceId,IMDSv2:MetadataOptions.HttpTokens}' --output table
# ---------------------------------------
# |         DescribeInstances           |
# +----------------------+--------------+
# |          ID          |   IMDSv2     |
# +----------------------+--------------+
# |  i-0abc123456789     |  optional    |
# |  i-0def987654321     |  required    |
# +----------------------+--------------+
```

`optional` = IMDSv1 enabled (vulnerable to SSRF). `required` = IMDSv2 only.

See [IMDSv1 Enabled Detection](https://hackindex.io/platforms/aws/vulnerability-discovery/ec2/ec2-imdsv1-enabled-detection) and [SSRF to IMDS Credential Theft](https://hackindex.io/platforms/aws/exploitation/ec2/ec2-ssrf-imds-credential-theft).
