SSRF Attacks: What They Are and Why Cloud Environments Make Them Dangerous
SSRF lets attackers reach internal services through your server. Learn how cloud metadata endpoints amplify the risk and how to defend against SSRF.
Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

When Your Server Becomes the Attacker
Server-Side Request Forgery (SSRF) is one of those vulnerabilities that barely registers on developers' radar until it hands an attacker the keys to your cloud infrastructure. The attack is deceptively simple: trick your server into making HTTP requests to internal resources the attacker can't reach directly. In cloud environments -- especially AWS -- this often means accessing the instance metadata endpoint at 169.254.169.254, which can return IAM credentials, and from there the attacker pivots into your entire AWS account.
The 2019 Capital One breach was SSRF. It exposed 106 million customer records because a misconfigured WAF allowed an attacker to reach the EC2 metadata service and retrieve temporary IAM credentials. That was seven years ago, and SSRF is now more prevalent than ever because modern applications make more outbound HTTP requests than ever -- to webhooks, URL previews, file imports, PDF generators, and third-party integrations.
What Is SSRF?
Definition: Server-Side Request Forgery (SSRF) is a vulnerability where an attacker can induce a server-side application to make HTTP requests to an arbitrary destination chosen by the attacker. This allows the attacker to reach internal services, cloud metadata endpoints, and private network resources that are not directly accessible from the internet.
How SSRF Works: Step by Step
- Find a server-side URL fetch. Any feature where your server fetches a URL based on user input is a potential SSRF vector: image imports, webhook delivery, URL previews, PDF rendering, file downloads.
- Supply an internal URL. Instead of a legitimate external URL, the attacker provides a URL pointing to an internal resource:
http://169.254.169.254/latest/meta-data/,http://localhost:6379/, orhttp://10.0.0.5:8080/admin. - The server makes the request. Because the request originates from your server (inside the network perimeter), firewalls and security groups allow it. The server sends the response back to the attacker.
- Extract sensitive data. The attacker reads internal API responses, metadata credentials, configuration files, or anything else accessible from the server's network position.
# Vulnerable endpoint: fetches a URL and returns the content
@app.route('/preview')
def url_preview():
url = request.args.get('url')
# No validation -- attacker controls the URL
response = requests.get(url)
return response.text
# Attack: GET /preview?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role
The response contains temporary AWS credentials: AccessKeyId, SecretAccessKey, and Token. With these, the attacker can call AWS APIs as your EC2 instance's IAM role.
Why Cloud Environments Make SSRF Devastating
The EC2 Metadata Endpoint
Every EC2 instance has access to a link-local metadata service at 169.254.169.254. It exposes instance information, user data scripts, and -- critically -- IAM role credentials. The original Instance Metadata Service (IMDSv1) responds to simple GET requests with no authentication. Any process on the instance (or any SSRF vulnerability) can read these credentials.
# What an attacker gets from the metadata endpoint
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role
{
"Code": "Success",
"AccessKeyId": "ASIA...",
"SecretAccessKey": "wJalr...",
"Token": "FwoGZX...",
"Expiration": "2026-04-07T18:00:00Z"
}
Beyond AWS: Other Cloud Metadata Services
| Cloud Provider | Metadata Endpoint | What It Exposes |
|---|---|---|
| AWS EC2 | 169.254.169.254 | IAM credentials, user data, instance info |
| GCP | metadata.google.internal (169.254.169.254) | Service account tokens, project metadata |
| Azure | 169.254.169.254 | Managed identity tokens, instance metadata |
| DigitalOcean | 169.254.169.254 | Droplet metadata, user data |
Every major cloud uses the same IP address for metadata. SSRF is a cross-cloud problem.
IMDSv2: A Partial Mitigation
AWS introduced Instance Metadata Service v2 (IMDSv2) as a defense against SSRF. Instead of responding to simple GET requests, IMDSv2 requires a session token obtained via a PUT request with a custom header:
# IMDSv2: requires a PUT to get a session token first
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
# Then use the token in subsequent requests
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role
This blocks basic SSRF attacks because most HTTP libraries follow redirects with GET requests and don't send custom headers. However, IMDSv2 isn't bulletproof:
- If the attacker can control the full HTTP request (method, headers), they can perform the PUT request.
- Some SSRF vulnerabilities allow arbitrary HTTP methods and headers (e.g., through SSRF in a proxy or HTTP client library).
- IMDSv2 is not enabled by default on all instance types. You must enforce it via launch templates or account-level settings.
Watch out: IMDSv2 is necessary but not sufficient. Enforce it across your account with
aws ec2 modify-instance-metadata-options --http-tokens required, but don't treat it as a complete SSRF defense. You still need input validation and network controls.
SSRF Attack Variants
Basic SSRF
The server fetches the attacker-supplied URL and returns the response. The attacker can read internal resources directly.
Blind SSRF
The server makes the request but doesn't return the response to the attacker. The attacker infers information from response timing, status codes, or by directing the request to an attacker-controlled server that logs the incoming connection (with headers that may contain internal data).
SSRF via URL Parsing Discrepancies
Different URL parsers handle edge cases differently. An attacker might use:
http://169.254.169.254encoded ashttp://0xa9fea9fe(decimal to hex)http://2852039166(decimal IP)http://[::ffff:169.254.169.254](IPv6-mapped IPv4)http://169.254.169.254.nip.io(DNS rebinding)http://attacker.com@169.254.169.254(URL authority confusion)
These bypass naive URL validation that only checks for the literal string 169.254.169.254.
How to Prevent SSRF
1. URL Validation with Allowlisting
The strongest defense is an allowlist of permitted domains or IP ranges. If your feature needs to fetch images from user-supplied URLs, restrict it to known image hosting domains. If it calls webhooks, validate against registered callback URLs.
from urllib.parse import urlparse
import ipaddress
import socket
ALLOWED_DOMAINS = {'images.unsplash.com', 'cdn.example.com'}
BLOCKED_RANGES = [
ipaddress.ip_network('169.254.0.0/16'), # Link-local
ipaddress.ip_network('10.0.0.0/8'), # Private
ipaddress.ip_network('172.16.0.0/12'), # Private
ipaddress.ip_network('192.168.0.0/16'), # Private
ipaddress.ip_network('127.0.0.0/8'), # Loopback
]
def is_url_safe(url: str) -> bool:
parsed = urlparse(url)
# Check scheme
if parsed.scheme not in ('http', 'https'):
return False
# Check domain allowlist
if parsed.hostname not in ALLOWED_DOMAINS:
return False
# Resolve DNS and check IP against blocked ranges
try:
ip = ipaddress.ip_address(socket.gethostbyname(parsed.hostname))
for blocked in BLOCKED_RANGES:
if ip in blocked:
return False
except (socket.gaierror, ValueError):
return False
return True
Pro tip: Always resolve the hostname to an IP and validate the IP against blocked ranges. Validating only the hostname is insufficient because DNS rebinding attacks can make a domain resolve to an internal IP between your validation check and the actual request.
2. Enforce IMDSv2 on All EC2 Instances
# Enforce IMDSv2 at instance launch
aws ec2 run-instances \
--metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1"
# Enforce for existing instances
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1
Setting HttpPutResponseHopLimit=1 prevents containers running on the instance from reaching the metadata service through the host's network stack.
3. Network-Level Egress Controls
Restrict what your application servers can reach on the network:
- Block outbound traffic to
169.254.169.254via iptables, security groups, or network policies. - Use an egress proxy that enforces URL allowlists for all outbound HTTP requests.
- In Kubernetes, use NetworkPolicies to restrict pod egress to specific CIDR ranges.
4. Disable Unnecessary URL Fetching
If a feature doesn't need to fetch arbitrary URLs, don't build it that way. Instead of letting users provide URLs for profile images, have them upload files directly. Instead of server-side URL previews, use client-side rendering.
SSRF Testing Tools and Costs
| Tool | Type | Cost | SSRF Detection |
|---|---|---|---|
| Burp Suite Pro | Web scanner | $449/yr | Collaborator for blind SSRF detection |
| OWASP ZAP | Web scanner (OSS) | Free | Active scan rules for SSRF |
| Nuclei | Vulnerability scanner (OSS) | Free | SSRF-specific templates |
| SSRFmap | SSRF exploitation (OSS) | Free | Automated SSRF exploitation and escalation |
| Snyk | SAST/DAST | Free tier available | Static analysis for SSRF patterns in code |
Frequently Asked Questions
What is the most common target of SSRF attacks in cloud environments?
The cloud instance metadata service at 169.254.169.254. This endpoint returns IAM credentials (AWS), service account tokens (GCP), or managed identity tokens (Azure) that let attackers access cloud APIs. It's reachable from any process on the instance and requires no authentication in IMDSv1.
Does IMDSv2 completely prevent SSRF on AWS?
No. IMDSv2 makes SSRF harder by requiring a PUT request with a custom header to obtain a session token. This blocks basic SSRF through HTTP redirects and simple GET-based fetches. But if the attacker can control the HTTP method and headers, they can still reach the metadata service. IMDSv2 is a necessary layer, not a complete solution.
Can SSRF affect non-cloud applications?
Yes. SSRF targets any internal resource reachable from the server: internal APIs, databases with HTTP interfaces (Elasticsearch, CouchDB), Redis instances, admin panels, and internal microservices. Cloud metadata is the highest-impact target, but SSRF is dangerous in any environment with internal services.
What is blind SSRF and how is it exploited?
Blind SSRF occurs when the server makes the request but doesn't return the response to the attacker. Attackers exploit it by directing requests to an attacker-controlled server to confirm the vulnerability, using timing differences to infer information, or chaining it with other vulnerabilities to extract data indirectly.
How do I test my application for SSRF?
Identify every feature that makes server-side HTTP requests based on user input. Test each with internal IPs (127.0.0.1, 169.254.169.254, 10.x.x.x), encoded IP variants, and DNS rebinding payloads. Use Burp Suite's Collaborator or a request bin to detect blind SSRF. Automate with tools like Nuclei's SSRF templates.
Is URL validation enough to prevent SSRF?
URL validation is necessary but has pitfalls. Attackers bypass hostname checks with IP encoding tricks, DNS rebinding, and URL parser inconsistencies. Effective validation requires resolving the hostname, checking the resulting IP against blocked ranges, and performing this check at request time -- not just at validation time. Combine with network-level egress controls.
What is DNS rebinding and how does it relate to SSRF?
DNS rebinding is a technique where a domain initially resolves to a safe external IP (passing validation), then quickly changes to resolve to an internal IP (127.0.0.1 or 169.254.169.254). If your application validates the URL and then makes the request in separate steps, the DNS resolution can change between them. Mitigate by pinning the resolved IP for the duration of the request.
Defense in Depth Is Non-Negotiable
SSRF is a problem that demands layered defenses because no single control is sufficient. Validate URLs with allowlists and IP range checks. Enforce IMDSv2 with a hop limit of 1. Block metadata IP ranges at the network level. Minimize server-side URL fetching features. Monitor outbound traffic for anomalous connections to internal IPs. The organizations that get breached via SSRF aren't the ones without any defenses -- they're the ones relying on a single layer that an attacker found a way around.
Written by
Abhishek Patel
Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.
Related Articles
Network Firewalls vs WAFs: Understanding Your Defense Layers
Network firewalls filter by IP and port at Layer 3/4. WAFs inspect HTTP content at Layer 7. Learn when you need each and how to configure them together.
10 min read
SecurityCertificate Management at Scale: Let's Encrypt, ACME, and cert-manager
Automate TLS certificates with Let's Encrypt, ACME protocol, and cert-manager in Kubernetes. Covers HTTP-01, DNS-01, wildcards, private CAs, and expiry monitoring.
9 min read
SecuritySQL Injection in 2026: Still a Problem, Here's How to Stop It
SQL injection remains a top vulnerability. Learn how SQLi works, why ORMs are not enough, and how to prevent it with parameterized queries and defense in depth.
9 min read
Enjoyed this article?
Get more like this in your inbox. No spam, unsubscribe anytime.