SSRF: Making the Server Fetch for You

Day 8 made the victim’s browser betray them. Today the server betrays itself. Server Side Request Forgery, SSRF, is the bug where you make a server send a request to a destination you choose, instead of the one it was meant to fetch. HackerOne has called SSRF the top vulnerability by payout for internet and online services companies, and the reason is simple: the server usually sits inside the network, with access you can never get from outside.
This is the sixth vulnerability class in the series. Where CSRF abused what the browser trusts, SSRF abuses what the server trusts, mainly itself.
Inside scope only, with minimal proof. SSRF can reach internal networks and cloud credentials. Confirm with timing, a harmless internal reach, or a request to a server you control. Never pull real internal data, and never retrieve and store live cloud credentials.
What SSRF actually is
Any feature that makes the server fetch a URL on your behalf is a candidate. Webhooks, URL previews, PDF generators, image fetchers, “import from URL,” SSO metadata fetchers, PDF-to-image converters, server-side screenshot tools, and anything that calls an internal microservice by address.
The pattern: you supply a URL, or something close to one, and the server’s own HTTP client requests it. The server trusts itself completely, and it often sits somewhere you cannot reach directly, inside a VPC, behind a firewall, or with a cloud identity attached. The request you control runs with the server’s network position.
The real report from Lyft shows the shape cleanly. A hacker researching the expense report feature found that submitting a URL as part of the workflow caused Lyft’s backend to make a request to that URL, which is SSRF by definition, and the researcher used it to demonstrate reach toward internal infrastructure.
Why it matters more since cloud
Before cloud, SSRF mostly got you access to internal services, databases, admin panels, things behind the firewall. Cloud computing added a second, often worse target: the instance metadata service.
On AWS, EC2 instances can query http://169.254.169.254/latest/meta-data/ for information about themselves, including, in the IMDSv1 configuration, temporary IAM credentials. An SSRF that can reach that address can potentially pull the exact access keys the server itself uses to talk to AWS. Azure and GCP have equivalent metadata endpoints at the same link-local address with different paths.
Two disclosed reports show the range of what this unlocks.
- Evernote, full read SSRF. The researcher found a full read SSRF that could leak AWS metadata and achieve local file inclusion, reaching both the cloud credentials and the local filesystem through the same bug. Report title on HackerOne Hacktivity: “Full read SSRF in www.evernote.com that can leak aws metadata and local file inclusion.”
- Shopify, SSRF in Exchange leading to root. A vulnerability in Shopify Exchange allowed SSRF that escalated to root access across all instances, one of the highest severity SSRF chains ever disclosed on the platform. Report title: “SSRF in Exchange leads to ROOT access in all instances.”
- Lyft, expense report SSRF. Reported by nahamsec, this one specifically demonstrated the risk of reaching AWS metadata instance keys and reading files on the internal network, and Lyft fixed it before it was exploited.
- HackerOne’s own program, SSRF via Analytics Reports. HackerOne paid $25,000 for an SSRF in its own analytics feature, one of the highest SSRF payouts on the platform, which tells you how seriously programs take a confirmed path to internal infrastructure.
The lesson across all four: SSRF severity is decided by what it reaches, not by the initial finding. A blind SSRF that only proves a DNS lookup is a low. The same bug reaching the metadata endpoint with working credential extraction is critical.
The two types
Basic (in band) SSRF. The response comes back to you. You see the fetched page’s content, an error with useful detail, or a redirect. Fast to confirm and easy to escalate because you get direct feedback.
Blind SSRF. Nothing comes back. You infer the request happened from a timing difference, an out-of-band callback to a server you control, or a side effect you can observe elsewhere. Slower to prove, often just as serious, and it is exactly what the Day 6 time-based SQLi mindset prepared you for: proving something happened without seeing the result directly.
Where to look, pointed at your recon
SSRF lives anywhere the application fetches a resource based on user input.
- Explicit URL parameters.
url=, callback=, webhook=, src=, dest=, redirect=, feed=, import=, path=. Your recon params.txt is the starting list.
- File and document generation. PDF generators, screenshot tools, and anything that renders a URL as HTML-to-PDF often lets you supply a URL inside the document content, not just a parameter.
- Webhooks and integrations. Payment notify URLs, Slack or Discord integration setup, SSO metadata URLs. The Razer report in this family was exactly a notify_url parameter.
- Image and avatar uploaders that accept a URL instead of a file. A classic and still common pattern.
- XML parsers. XXE, covered more fully elsewhere, can itself trigger SSRF through external entity fetches, so any endpoint accepting XML is worth testing for both.
- Anything your recon JS files reference as an internal API call by hostname. If the frontend calls a path like
/internal/ or references a service name, the backend that proxies it is a candidate.
How to hunt it, step by step
Step 1: find anything that fetches on your behalf. From recon, list every feature where the server plausibly makes an outbound request based on your input.
Step 2: confirm basic reach. Point the parameter at a URL on a server you control, a free request bin or a simple logging endpoint works well. If you see a hit in your logs, the server fetched it. Note the User-Agent and headers it sent, they often reveal the backend stack.
Step 3: probe internal reach. Once basic SSRF is confirmed, try internal targets:
http://127.0.0.1/ and common internal ports: 22, 80, 443, 3306, 6379, 9200, 8080, 8443
http://169.254.169.254/latest/meta-data/ for AWS, http://169.254.169.254/metadata/instance?api-version=2021-02-01 with a Metadata: true header for Azure, and http://metadata.google.internal/computeMetadata/v1/ with a Metadata-Flavor: Google header for GCP
- Internal hostnames guessed from your recon, like
admin.internal, api.internal, or service names seen in JS files or error messages
Step 4: if direct IPs are filtered, try bypasses. Developers often filter obvious internal IPs, not the many ways to express them.
- Alternate IP encodings: decimal (
2130706433 for 127.0.0.1), octal, hex, or IPv6 (::1 or ::ffff:127.0.0.1)
- DNS rebinding: a domain you control that first resolves to a benign IP, passes validation, then resolves to an internal IP on the actual fetch
- Open redirects on an allowed domain, chaining through a trusted host to redirect into an internal one
- URL parsing confusion, like
http://trusted.com@127.0.0.1/ or http://127.0.0.1#trusted.com, which some fetchers parse inconsistently
- Protocol smuggling: trying
file://, gopher://, or dict:// where the fetcher does not restrict schemes
Step 5: escalate on cloud metadata. If step 3 confirms metadata reach, pull only the instance role name and a single credential block as minimal proof, never use the credentials against real AWS APIs, and report it immediately. The researcher’s job is to prove reach, not to pivot into the live account.
Step 6: for blind cases, use timing and out-of-band. Compare response time for a request to an internal, likely-closed port versus an external one. A consistent multi-second delay difference is a timing signal, the same discipline from Day 6’s time-based SQLi. Pair it with an out-of-band service to catch DNS lookups or HTTP callbacks you cannot otherwise see.
Writing the SSRF report
Title: SSRF in [feature/parameter] at [endpoint] reaching [internal target]
Summary:
One sentence: which parameter, which endpoint, what internal or
cloud resource was reached.
Steps to Reproduce:
1. Send [request] with [attacker-controlled URL] in [parameter].
2. Observe [callback received / internal response / timing delta]
confirming the server made the request.
3. Point the parameter at [internal target / metadata endpoint]
and show [minimal proof: service banner, metadata path listing,
role name].
(Exact requests, logs from your listener, screenshots, timing data.)
Impact:
The server can be made to issue requests to internal infrastructure
and cloud metadata endpoints. This may expose internal services,
cloud credentials, or [specific reached resource]. State the worst
reasonably demonstrated outcome, not a hypothetical one.
Remediation:
Allowlist permitted destination hosts and schemes server side.
Block requests to link-local, loopback, and private IP ranges at
the network layer. Disable IMDSv1 or enforce IMDSv2 with hop-limit
protections on cloud instances. Do not rely on blocklists alone,
since encoding and redirect bypasses defeat them.
Strong SSRF reports share a pattern worth copying. They prove server-side origin with a callback or timing signal, they escalate to the most serious reasonably demonstrated target, usually the metadata endpoint, and they stop at proof, the role name or a listing, not a live credential pull. That restraint is both ethical and what makes severity easy for the triager to agree with.
What programs often reject
- Self-XSS-style SSRF where only the researcher’s own browser is affected
- DNS resolution alone with no further internal reach demonstrated
- SSRF against a feature explicitly scoped as “known to fetch arbitrary URLs by design,” like a legitimate web proxy product
- Findings where you cannot show the request originated server side rather than client side
The mindset: the server is also a user you do not control
SQLi, XSS, and CSRF all abuse something that trusts input blindly. SSRF is the same lens turned on the server’s own outbound requests: the server trusts its own HTTP client completely, and anywhere user input shapes the destination of that client, the server’s network position becomes yours to borrow. Once you see this, every “fetch this URL for me” feature looks different.
Homework for Day 9
- From recon, list every feature that plausibly fetches a URL server side: webhooks, importers, PDF or screenshot generators, avatar-by-URL, SSO metadata fetchers.
- Test basic reach with a listener you control, and note the response headers and User-Agent the server sends.
- Probe internal IPs, common ports, and the cloud metadata endpoint relevant to the target’s hosting provider.
- Where direct access is filtered, try at least two bypass techniques: alternate IP encoding and an open redirect chain.
- Read the Lyft report and the HackerOne $25,000 Analytics Reports report end to end (search the exact titles on HackerOne Hacktivity). For each, note the feature abused, how internal reach was proven, and how far escalation went.
A confirmed SSRF reaching cloud metadata or an internal service is typically high or critical severity. Document it with the listener evidence, the minimal metadata proof, and the allowlist-based remediation.
Day 10 moves to a bug that hides in how the server parses structured data instead of what it fetches, XML External Entity injection, and how it chains with the SSRF technique you just learned.