>samit_hota
Back to research
ETHICAL HACKING

Beyond URL Fetching: How IMDSv1 Turns SSRF into Full Cloud Compromise

Samit Hota·
#ssrf#aws#cloud-security#imds

The Fallacy of the “Low-Impact” SSRF

Many development teams treat internal HTTP fetching vulnerabilities as low-severity bugs, assuming internal network isolation or lack of local administrative privileges renders them harmless. In cloud environments running Instance Metadata Service Version 1 (IMDSv1), this assumption fails completely. Because IMDSv1 accepts unauthenticated HTTP GET requests, any application endpoint that allows an attacker to control a URL target can query the link-local address 169.254.169.254 directly from the hosting compute instance.

This architectural oversight transforms a standard application-level flaw into full cloud infrastructure access. When an EC2 instance is assigned an IAM role, temporary AWS credentials are systematically exposed through this metadata endpoint.

Traversing IMDSv1 via Unauthenticated GET Requests

When a Server-Side Request Forgery (SSRF) vulnerability exists in a web application—such as an image preview fetcher, PDF renderer, or webhook tester—the backend server executes HTTP requests supplied by the client.

In IMDSv1, fetching metadata requires nothing more than standard GET requests. An attacker leverages the SSRF flaw to query the top-level metadata path:

GET /latest/meta-data/ HTTP/1.1
Host: 169.254.169.254
Connection: close

To locate IAM role credentials attached to the EC2 instance, the request targets the security credentials endpoint:

GET /latest/meta-data/iam/security-credentials/ HTTP/1.1
Host: 169.254.169.254
Connection: close

This request returns the name of the assigned IAM role (for example, web-application-role). Querying that specific role path returns the temporary security credentials assigned to the instance:

GET /latest/meta-data/iam/security-credentials/web-application-role HTTP/1.1
Host: 169.254.169.254
Connection: close

The metadata service responds with a JSON object containing AccessKeyId, SecretAccessKey, Token, and Expiration.

Leveraging Extracted Credentials for Cloud Access

Once temporary credentials are extracted, the impact shifts from local application context to the broader cloud infrastructure control plane.

The returned credentials can be configured locally using standard environment variables:

export AWS_ACCESS_KEY_ID="ASIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_SESSION_TOKEN="..."

With these variables set, any call using the AWS CLI or SDKs executes with the identity and permissions of the compromised EC2 instance:

aws sts get-caller-identity

If the role follows overly permissive policies—such as wildcard S3 read permissions or administrative privileges—the compromise expands to cloud storage buckets, internal databases, or secondary services within the AWS account.

How IMDSv2 Neutralizes Simple SSRF

AWS introduced IMDSv2 specifically to address the structural weaknesses of IMDSv1. IMDSv2 transitions from simple GET requests to a session-oriented token architecture.

To retrieve metadata under IMDSv2, a client must first issue a PUT request containing a TTL header to obtain a session token:

PUT /latest/api/token HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token-ttl-seconds: 21600
Connection: close

The service returns a signed token string. Subsequent metadata requests must include this token in a custom header:

GET /latest/meta-data/iam/security-credentials/web-application-role HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token: <token_value>
Connection: close

This design breaks standard SSRF attack paths due to three key properties:

  1. Most SSRF vulnerabilities are restricted to GET or POST requests, blocking the required PUT call.
  2. Most SSRF vectors do not allow setting arbitrary custom HTTP headers like X-aws-ec2-metadata-token.
  3. IMDSv2 token requests do not accept forwarded headers via HTTP redirects (301/302).

Defense in Depth: Enforcing IMDSv2 and Egress Rules

Preventing cloud account compromise requires enforcing IMDSv2 at the infrastructure level and restricting network access to the metadata IP.

To mandate IMDSv2 across an EC2 instance using the AWS CLI, update the instance metadata options:

aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890example \
    --http-tokens required \
    --http-put-response-hop-limit 1 \
    --endpoint-url https://ec2.us-east-1.amazonaws.com

Setting --http-put-response-hop-limit 1 is critical for containerized environments. When running workloads inside Docker or Kubernetes, a hop limit of 1 ensures that PUT requests originating inside a container network bridge cannot reach the host’s metadata endpoint, as the IP packet’s Time-To-Live (TTL) expires when traversing the network boundary.

Finally, restrict outbound network access from application containers so that endpoints without an explicit operational requirement are denied outbound connection paths to 169.254.169.254/32.

Want a second set of eyes on your security posture?

Let's talk about where your real exposure is.

Book an advisory call