Lorem, ipsum dolor sit amet consectetur adipisicing elit. Qui, itaque voluptate ipsa non enim amet ducimus voluptatibus deserunt nam esse!
Server-Side Request Forgery (SSRF): Exploiting Trust in Internal Networks

Server-Side Request Forgery (SSRF): Exploiting Trust in Internal Networks

pr0h0
ssrfweb-securitynetwork-securitycybersecurity
AI Usage (92%)

When I test SSRF, I ignore the acronym for a minute and look at the trust boundary. The bug is usually not “the app can fetch a URL.” The bug is that server-side fetches often inherit network reach, credentials, and assumptions the user should never get.

Why SSRF is really about trust boundaries

A user-controlled URL becomes dangerous when the server treats it like a trusted destination. That can mean the backend reaches internal hosts, metadata services, or private admin panels that are invisible from the browser.

The real question is simple: who is making the request, and what can that requester reach?

If the answer is “our production backend inside the VPC,” the impact can be much larger than a basic outbound request. I usually map SSRF across three layers:

LayerWhat to checkWhy it matters
InputCan the attacker control the target URL?This is the entry point
NetworkWhere can the server reach?Internal services may be exposed
ResponseIs the response reflected or processed?Data can leak even without direct display

Where SSRF shows up in real applications

SSRF rarely appears as a feature literally called “fetch arbitrary URL.” It shows up in convenience paths.

URL fetchers, webhooks, and import features

Anything that ingests a URL is worth testing:

  • webhook validators
  • URL preview endpoints
  • document importers
  • feed readers
  • SSO metadata fetchers
  • callback verification flows

The mistake is usually trusting a URL parameter after a shallow validation step. I have seen systems reject 127.0.0.1 but still accept alternate encodings, redirects, or a hostname that resolves to a private IP later.

Image proxies, link previews, and PDF generators

These are common because they look harmless. The server downloads content, maybe resizes it, then returns a cached copy.

The danger is in the fetch itself:

  • redirects can move the request to a different host
  • DNS can resolve to internal addresses after validation
  • response parsing may leak headers or body data
  • PDF generators may fetch remote assets during rendering

If the server can reach something the user cannot, the feature has a wider blast radius than the UI suggests.

How to reproduce SSRF safely

I keep the first test boring on purpose. Use harmless endpoints you control. Do not jump straight to internal targets.

Start with harmless external endpoints

Use a test server that logs requests and returns a simple body. Then submit a URL you fully control and confirm:

  1. the backend makes the request
  2. the backend follows or rejects redirects
  3. the backend preserves or strips headers
  4. the backend exposes timing differences you can observe

A quick probe looks like this:

const url = "https://example.test/ssrf-probe?case=1";

const res = await fetch("/api/fetch-url", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ url })
});

console.log(await res.text());

You are not looking for success yet. You are looking for behavior: timeout handling, redirect behavior, and whether the application tells you anything useful about the fetch path.

Watch for redirects, DNS resolution, and header control

These three details matter more than the response body in many tests:

  • Redirects: a safe-looking URL can redirect to an unsafe destination.
  • DNS resolution: allowlists that check only the hostname string can miss private IP resolution.
  • Header control: if the server forwards cookies, bearer tokens, or internal headers, the impact grows fast.
💪

Test both the exact URL you submit and the final destination after redirects. The difference is often where the bug lives.

What changes when the request comes from the server

A browser request is limited by same-origin rules, user auth, and client-side sandboxing. A server request usually is not.

Internal network reachability and metadata services

This is the classic SSRF consequence: the backend can often reach services that are not publicly exposed. That may include internal APIs, admin dashboards, service discovery endpoints, or cloud metadata services.

The useful part is not just reachability. It is privilege. A server may present a trusted network identity, and that identity can unlock data the original user never had.

Privilege leakage through shared infrastructure

In shared environments, SSRF can cross trust lines in uncomfortable ways:

  • a worker can talk to another service's admin port
  • a preview bot can fetch content from internal tools
  • a build system can read endpoints meant only for deployment jobs

I have seen “just fetch this URL” turn into a path to internal session data, operational metadata, or environment-specific configuration.

Defensive checks that actually matter

Allowlists, parsing rules, and redirect handling

The defense should live in the backend, not in a thin client-side check.

A practical baseline:

  • use an allowlist of domains you actually expect
  • parse URLs with a real parser, not string matching
  • normalize scheme, host, and port before validation
  • block private IP ranges and localhost
  • disable redirects unless you explicitly need them
  • re-validate every redirect hop if redirects are allowed

If you only check the first URL string, you are trusting the attacker's interpretation of that string.

Network egress controls and metadata protection

Application code is not enough by itself. I look for defense in depth:

  • restrict outbound traffic from the service
  • deny access to internal CIDRs unless required
  • block cloud metadata endpoints at the network layer
  • use short-lived credentials and scoped service roles
  • log outbound destinations for review
⚠️

Do not rely on “nobody should know the internal address.” SSRF breaks that assumption quickly.

Reporting impact without exaggeration

A good SSRF report should be concrete. Show what the server can reach, what it can return, and what trust boundary it crosses.

Useful impact statements sound like this:

  • “A low-privilege user can make the backend reach internal-only services.”
  • “The application follows redirects and can be steered to unexpected destinations.”
  • “The server can access cloud metadata or private admin endpoints if deployed in a permissive network.”

Avoid inflated language. If you did not prove metadata access, do not claim it. If you did not prove response exfiltration, say the issue is reachability with possible expansion depending on deployment.

Conclusion

SSRF is not just an input validation bug. It is a mistake about who should be trusted to speak to which network. Once you test it that way, the dangerous cases become easier to find: internal reachability, redirect abuse, and server-side privilege the browser never had.

The fix is also a trust-boundary fix. Parse strictly, allowlist carefully, control egress, and treat every server-side fetch as a security-sensitive action.

Share this post

More posts

Comments