This issue has been assessed as critical severity. Review affected configurations immediately.
Server-Side Request Forgery (SSRF) vulnerabilities have become one of the most consequential attack classes in cloud environments. What would be a moderate SSRF in a traditional network — access to internal services on RFC 1918 ranges — becomes a critical credential theft in cloud environments because every hyperscaler exposes a metadata service at a well-known link-local address that returns short-lived credentials for the instance’s attached identity.
The Metadata Service Addresses
Each major cloud provider exposes IMDS at a fixed link-local address:
| Provider | IMDS Address | Credential Path |
|---|---|---|
| AWS | 169.254.169.254 | /latest/meta-data/iam/security-credentials/<role-name> |
| Azure | 169.254.169.254 | /metadata/identity/oauth2/token?api-version=2018-02-01 |
| GCP | metadata.google.internal / 169.254.169.254 | /computeMetadata/v1/instance/service-accounts/default/token |
| Alibaba Cloud | 100.100.100.200 | /latest/meta-data/ram/security-credentials/<role> |
These addresses are non-routable from the internet and not reachable from other instances within a VPC — they’re only accessible from the instance itself. An SSRF vulnerability in an application running on the instance is a bridge from the internet to these endpoints.
IMDSv1: Single-Request Credential Theft
AWS’s first-generation IMDS (IMDSv1) is a simple HTTP service: no authentication, no headers required. A single GET request returns credentials:
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/
This returns the role name(s) attached to the instance. A second request retrieves temporary credentials:
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/MyEC2Role
Response:
{
"Code": "Success",
"Type": "AWS-HMAC",
"AccessKeyId": "ASIA...",
"SecretAccessKey": "wJalrXUtnFEMI...",
"Token": "IQoJb3JpZ2luX2Vj...",
"Expiration": "2026-05-06T18:00:00Z"
}
These are fully functional AWS API credentials valid for the expiration time (typically 1–6 hours). An attacker who can trigger an SSRF to these two endpoints has the equivalent of a ~/.aws/credentials file for the instance’s IAM role — from anywhere on the internet.
The Capital One Breach (2019)
The most documented cloud SSRF breach. A misconfigured Web Application Firewall (AWS WAF deployed on EC2) allowed SSRF due to an overly permissive rule. The attacker:
- Exploited an SSRF via the WAF’s proxy functionality
- Queried IMDSv1 to retrieve credentials for the EC2 instance role
- Used those credentials to list and download 106 million customer records from S3
The instance role had s3:GetObject on sensitive buckets — a broad permission that wouldn’t flag monitoring. The SSRF was the entry point; the excessive IAM permissions were the blast radius amplifier.
IMDSv2: Token-Based Mitigation
AWS introduced IMDSv2 in 2019 as a defense-in-depth measure. IMDSv2 requires a PUT request to obtain a session token before making GET requests:
# Step 1: Get a session token (requires PUT method, sets TTL)
TOKEN=$(curl -s -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 -s -H "X-aws-ec2-metadata-token: $TOKEN" \
"http://169.254.169.254/latest/meta-data/iam/security-credentials/MyEC2Role"
Why this matters for SSRF: Many SSRF vulnerabilities exploit URL-fetching functionality that only supports GET requests — a fetch() call, an image proxy, an XML parser following xinclude or external entity references. These cannot issue the required PUT request with a custom header to obtain the token. IMDSv2 breaks the one-request exploitation chain.
IMDSv2 Bypasses
IMDSv2 is not a panacea:
-
SSRF with full HTTP control — If the SSRF allows arbitrary HTTP methods and custom headers (e.g., a server-side proxy, a misconfigured reverse proxy), IMDSv2 provides no protection.
-
Open redirects on the instance — If an application on the instance has an open redirect that allows redirecting to
http://169.254.169.254/, and the SSRF vulnerability follows redirects, the two-step exchange can be replayed through the redirect chain. -
Cloud function SSRF — Lambda functions, Azure Functions, and Cloud Run don’t have the same IMDS structure as VMs, but Lambda’s internal runtime API (
AWS_CONTAINER_CREDENTIALS_FULL_URI) is a similar vector.
GCP Metadata Service
GCP’s IMDS at metadata.google.internal requires a specific header to prevent browser-based attacks:
curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
The Metadata-Flavor: Google header requirement is analogous to Azure’s Metadata: true — it’s a single custom header that’s easy to set in most SSRF contexts but prevents casual browser navigation or basic redirect-following attacks.
GCP also exposes sensitive data beyond tokens:
# SSH public keys
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/project/attributes/ssh-keys
# Startup scripts (often contain secrets)
curl -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/attributes/startup-script
Startup scripts frequently contain environment variables, API keys, and database URLs, making the GCP metadata endpoint even higher value than just the service account token.
Detection
AWS: CloudTrail + GuardDuty
GuardDuty has a dedicated finding type: UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS. This fires when instance credentials are used from an IP address outside AWS infrastructure — the most reliable signal of SSRF-driven credential theft.
aws guardduty list-findings \
--detector-id <detector-id> \
--finding-criteria '{"Criterion":{"type":{"Eq":["UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration.OutsideAWS"]}}}'
Honeytokens
Deploy canary credentials using Canarytokens or thinkst canaries embedded in the metadata service (via UserData or instance tags). Any usage of these credentials immediately alerts — with source IP and full API call details.
Remediation Checklist
- Enforce IMDSv2 on all EC2 instances:
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1
The --http-put-response-hop-limit 1 ensures the token cannot be obtained from a container inside the instance — essential for preventing container escape chains.
- Enforce via launch template:
{
"MetadataOptions": {
"HttpTokens": "required",
"HttpEndpoint": "enabled",
"HttpPutResponseHopLimit": 1
}
}
- Apply IMDSv2 enforcement as an SCP:
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
}
- Use IMDSv2 enforcement in Terraform:
resource "aws_instance" "secure" {
...
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
}
- Apply least-privilege instance roles — the SSRF blast radius is proportional to the instance role’s permissions. An instance role with read-only access to a specific S3 prefix is dramatically less impactful than one with broad access.
SSRF to IMDS is a class of vulnerability that will continue to exist as long as web applications proxy external URLs. IMDSv2 significantly raises the bar for exploitation, but defense in depth — minimal instance permissions, network-level IMDS restriction where possible, and real-time credential use monitoring — is the complete control set.