SSRF Vulnerability: Server-Side Request Forgery Explained
An SSRF vulnerability (Server-Side Request Forgery) occurs when an attacker can cause a server to make HTTP requests to an arbitrary destination — including internal network resources, cloud metadata endpoints, and services not intended to be externally accessible. SSRF has become one of the most critical vulnerability classes in cloud-native applications, responsible for major breaches including the 2019 Capital One breach that exposed 100 million records.
Does your server fetch remote URLs? [Scan for SSRF indicators with ZeriFlow](https://zeriflow.com) — free, 80+ checks.
How SSRF Attacks Work
SSRF exploits functionality that requires your server to fetch a remote resource — image processors, URL preview generators, webhook validators, PDF renderers, health checks, or any feature where a user supplies a URL.
Basic SSRF Example
POST /api/fetch-preview
{"url": "https://example.com/image.png"}An attacker replaces the URL:
POST /api/fetch-preview
{"url": "http://localhost:8080/admin"}The server makes the request from its own context — bypassing firewall rules that block external access to the admin interface. The server returns the response to the attacker.
The Cloud Metadata Goldmine
The most dangerous SSRF target in cloud environments is the Instance Metadata Service (IMDS). Every major cloud provider exposes a special IP address reachable only from within the instance:
- AWS:
http://169.254.169.254/latest/meta-data/ - GCP:
http://metadata.google.internal/computeMetadata/v1/ - Azure:
http://169.254.169.254/metadata/instance?api-version=2021-02-01
Via an SSRF vulnerability, an attacker can retrieve:
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/
→ {"RoleName": "EC2-Production-Role"}
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2-Production-Role
→ {
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"Token": "...",
"Expiration": "2024-..."
}These temporary credentials provide full AWS API access with the permissions of the EC2 role — potentially including S3 bucket access, RDS credentials, and more.
This is exactly what happened in the Capital One breach. A misconfigured WAF allowed SSRF to the metadata service, which returned credentials, which were used to exfiltrate data from 700+ S3 buckets.
SSRF Attack Vectors
URL Parameters
The most obvious: any parameter that accepts a URL.
?url=https://...
?image=https://...
?webhook=https://...
?callback=https://...
?redirect=https://...Import / Fetch Features
- "Import from URL" in document editors
- "Fetch RSS feed" in news aggregators
- "Download profile picture from URL"
- PDF generators that render external images
- Webhook test/preview functionality
XML and Document Formats
XML parsers that resolve external entities (XXE) are often used for SSRF-equivalent attacks. SVG files can trigger HTTP requests via <image href='http://internal-server/'>.
DNS Rebinding
A sophisticated SSRF bypass: the attacker controls a domain that first resolves to an allowed IP (passes validation), then rebinds to 169.254.169.254 when the actual request is made. The check and the use happen at different times.
SSRF Bypass Techniques
Basic URL filters are easily bypassed:
| Target | Bypass Technique |
|---|---|
http://169.254.169.254 | http://169.254.169.254 decimal: http://2852039166 |
http://127.0.0.1 | http://localhost, http://[::1], http://0.0.0.0 |
http://internal-host | DNS pointing to private IP |
| Blocked scheme | file:///etc/passwd, dict://, gopher:// |
Gopher protocol is particularly dangerous — it allows constructing arbitrary TCP payloads, enabling SSRF to exploit Redis, Memcached, and other services that don't speak HTTP.
Prevention: The Allowlist Architecture
The primary defense against SSRF is strict allowlisting of permitted destinations.
Server-Side URL Allowlist
import ipaddress, socket
from urllib.parse import urlparse
ALLOWED_SCHEMES = {'https', 'http'}
ALLOWED_HOSTS = {
'api.trusted-service.com',
'cdn.myapp.com',
'webhooks.slack.com'
}
PRIVATE_RANGES = [
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('127.0.0.0/8'),
ipaddress.ip_network('169.254.0.0/16'), # link-local / IMDS
ipaddress.ip_network('::1/128'),
ipaddress.ip_network('fc00::/7'),
]
def is_safe_url(url):
parsed = urlparse(url)
# Check scheme
if parsed.scheme not in ALLOWED_SCHEMES:
raise ValueError(f'Scheme {parsed.scheme} not allowed')
# Resolve hostname to IP
try:
ip_str = socket.gethostbyname(parsed.hostname)
ip = ipaddress.ip_address(ip_str)
except socket.gaierror:
raise ValueError('Could not resolve hostname')
# Block private/internal IPs
for private_range in PRIVATE_RANGES:
if ip in private_range:
raise ValueError(f'IP {ip} is in private range {private_range}')
# Optionally: enforce allowlist of hosts
if ALLOWED_HOSTS and parsed.hostname not in ALLOWED_HOSTS:
raise ValueError(f'Host {parsed.hostname} not in allowlist')
return TrueImportant: Resolve DNS at validation time and use the resolved IP for the actual request to prevent DNS rebinding attacks.
AWS IMDSv2: Closing the Metadata Gap
AWS introduced IMDSv2 to mitigate SSRF attacks against the metadata service. IMDSv2 requires a PUT request to obtain a session token, which must then be included in subsequent requests:
# IMDSv1 (vulnerable to SSRF)
curl http://169.254.169.254/latest/meta-data/
# IMDSv2 (resistant to SSRF — requires PUT first)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/SSRF vulnerabilities typically can only make GET requests — they can't perform the PUT preflighted request required by IMDSv2.
Enable IMDSv2 for all EC2 instances. This should be enforced via AWS Config rules and instance launch templates.
ZeriFlow SSRF Guard
ZeriFlow includes SSRF guard checks as part of its security scan — looking for indicators that your application may have SSRF exposure points: URL parameter patterns, redirect chains that reach internal addresses, and server configurations that don't apply appropriate egress filtering.
Run a free SSRF-aware scan on your application at ZeriFlow.
Network-Level Defense
Even with application-level controls, implement network controls as defense-in-depth:
# Egress firewall rule: block metadata IPs at network level
# AWS Security Group / NACLs:
# Deny outbound to 169.254.169.254/32
# Deny outbound to 10.0.0.0/8 (if web servers shouldn't reach internal services)
# iptables equivalent (Linux host):
iptables -A OUTPUT -d 169.254.169.254 -j DROP
iptables -A OUTPUT -d 127.0.0.0/8 -j DROPAlso consider running your URL-fetching functionality in a dedicated microservice with severely restricted network access — it can only reach the internet, not your internal network.
FAQ
Q: How is SSRF different from CSRF?
A: CSRF (Cross-Site Request Forgery) tricks the user's browser into making requests. SSRF tricks the server itself into making requests. SSRF is generally more dangerous because the server has access to internal networks, metadata services, and resources not reachable from the user's browser.
Q: Can SSRF lead to remote code execution?
A: Yes, in several ways. Via cloud metadata credentials that provide AWS/GCP API access. Via gopher:// protocol attacking Redis, which can write files or execute commands. Via internal admin interfaces (Jenkins, Elasticsearch) accessible only internally. Via access to internal CI/CD systems. SSRF to RCE is a documented attack chain.
Q: Is SSRF a risk for serverless functions (Lambda, Cloud Functions)?
A: Yes. Serverless functions also have access to instance metadata and internal services. AWS Lambda functions can access the metadata endpoint at 169.254.169.254. Apply the same validation controls. Enable IMDSv2. Use IAM least-privilege roles so that even if credentials are stolen, the blast radius is limited.
Q: What is blind SSRF?
A: In blind SSRF, the server makes the request but doesn't return the response to the attacker. The attacker can still confirm the vulnerability by observing out-of-band signals — DNS lookups, HTTP requests to attacker-controlled servers, or timing differences. Blind SSRF can still reach internal services and cloud metadata even without seeing the response directly.
Q: Does ZeriFlow test for SSRF directly?
A: ZeriFlow performs passive scanning for SSRF-related misconfigurations and indicators, including egress control signals and URL parameter exposure patterns. For active SSRF testing, combine ZeriFlow's baseline scan with targeted manual testing. Start your free scan at ZeriFlow.
Conclusion
SSRF vulnerabilities have caused some of the largest data breaches in cloud computing history. The attack is elegant: weaponize the server's privileged network position to access resources no external attacker could reach directly. Cloud metadata endpoints make this catastrophically impactful — one SSRF can become full cloud account compromise.
Defense requires both application-level allowlisting (validate and resolve URLs before fetching) and network-level controls (block egress to metadata IPs, restrict internal access). Enabling IMDSv2 on all cloud instances is a quick win that significantly reduces SSRF impact.
[Scan your application with ZeriFlow](https://zeriflow.com) to baseline your security posture across 80+ checks, including SSRF indicators. Free, instant, no account needed.