Server-side request forgery earned its own entry in the OWASP Top 10. Explain the trust property it violates, and why blocking private and loopback address ranges is a weaker defence than an allow-list of permitted destinations.
answer
- confused deputy: attacker's URL, server's network position
- blind SSRF still leaks via status/timing, and can write state
- deny-list = open world, allow-list = closed world
- resolve once, validate the resolved address, pin the connection
- re-check every redirect hop; restrict schemes; egress proxy
basics
~20 sThe server becomes a confused deputy: it makes a request an attacker chose, but with the server's network position and credentials. Blocking bad addresses is an open-world deny-list — redirects, DNS re-resolution and address encodings keep producing new bypasses — while an enumerated allow-list of destinations is closed and finite.
solid answer
~60 sSSRF exploits the fact that internal services usually authorise by **network position**, not identity. An attacker who cannot reach an internal endpoint supplies a URL to an application that can, and the request arrives with the server's source address, its VPC membership, its instance credentials and any implicit trust that follows. The response, an error difference or a timing difference then acts as an oracle even when the body is never returned. A deny-list of private ranges is an **open-world** control: you must anticipate every representation of a forbidden destination — alternative address encodings, redirect chains, hostnames that resolve to internal addresses, re-resolution between the check and the connection (a time-of-check/time-of-use gap), and non-HTTP schemes. Each bypass is a new special case. An **allow-list** of destinations is closed-world and finite: the code owns the set of hosts, ports and schemes it will ever contact. It must be enforced on the resolved address at connect time and re-enforced on every redirect, or the attacker simply moves the target one hop later.
go deeper
Say the server fetches a URL the user supplied, so the attacker reaches internal systems using the server's access; the fix is a list of allowed destinations, not a list of banned ones.
Add the bypass mechanics — address encodings, attacker-controlled DNS, redirect chains — and explain the open-world versus closed-world argument for allow-listing.
Cover resolve-once-and-pin, per-redirect re-checking, scheme restriction, and the blind-SSRF oracles; note that cloud metadata makes network position equal to identity.
Argue the architectural fix: a dedicated egress path with no route to management planes and authenticated internal services, so a bypass reaches nothing worth having and network position is no longer an authorisation decision.
## The trust property SSRF is a *confused deputy* problem. A deputy holds authority that the requester does not, and can be tricked into exercising it on the requester's behalf. Here the deputy is the application server: it sits inside a trusted network segment, it can reach management interfaces, metadata services, databases, message brokers and internal APIs, and many of those endpoints authorise callers implicitly because "anything that can reach me is inside". When the application fetches a URL that the user supplied — an image to thumbnail, a webhook to call, a document to import, a link to preview, an XML document with an external entity reference — the attacker borrows all of that authority without ever holding it. So the violated invariant is: **the destination of an outbound request is a decision the application must own, never a value it accepts.** The same invariant family as injection appears here — an attacker-controlled value reaches a component that interprets it as an instruction (a destination) rather than as data — but the sink is a network client rather than a parser. ## Impact even without a response body A common mistake is to score SSRF low because the fetched body is not returned to the user. Three channels remain. Differences in status or error text distinguish open from closed ports and existing from missing hosts, turning the server into an internal port scanner. Timing does the same when errors are uniform. And many high-value targets need no response at all: a request that *arrives* at an internal administrative endpoint can change state, and cloud instance-metadata services historically returned credentials to any local GET. Blind SSRF is still SSRF. ## Why deny-lists lose The defence ladder for this sink reads: enumeration of permitted destinations at the top (structural separation is unavailable because the whole point of the feature is to make a network call), then transformation and normalisation, then validation by pattern, then detection through egress monitoring. The reason the enumerated allow-list occupies the top rung is the **open-world versus closed-world** argument. A deny-list must describe the infinite set of destinations you do not want, in an addressing system that offers many representations of the same host: decimal and octal and hexadecimal integer forms of an address, IPv6 forms including IPv4-mapped addresses, hostnames under attacker control that resolve to internal addresses, wildcard DNS services that resolve any label to an arbitrary address, and internal names that are not addresses at all. An allow-list describes the finite set you do want — the three partner hosts on port 443 over HTTPS — and every unlisted destination is refused by default. Adding a new representation trick does not expand a finite set. ## The two ordering traps Even a correct allow-list fails if it is applied at the wrong moment. **Time-of-check to time-of-use on resolution.** Validating the hostname, then handing the URL to a client that resolves it again, allows a DNS answer to change between the two lookups (DNS rebinding): the check sees a public address, the connection goes to an internal one. The fix is to resolve once, validate the *resolved address*, and connect to that address — pinning the connection to the address that was actually checked. **Redirects.** A permitted host may answer with a redirect to a forbidden one. If the HTTP client follows redirects transparently, the allow-list was applied only to the first hop. Either disable automatic redirect following and re-run the full check on each new location, or supply a per-hop hook that does. ## Controls that survive contact with reality Beyond the allow-list, the durable answer is architectural. Constrain the *scheme* set to HTTP and HTTPS, because file, gopher, ftp and mail schemes turn a fetch into something else entirely. Route all user-influenced outbound traffic through a dedicated egress proxy in a segment with no route to internal management planes, so that even a bypass reaches nothing valuable — this is the network-level expression of least privilege. Give the fetching component its own low-privilege identity rather than an ambient instance identity, and require internal services to authenticate callers so that network position stops being an authorisation decision at all; that removes the deputy's excess authority rather than trying to police its instructions. Cap response size, redirect count and timeouts to bound resource abuse. Finally, log outbound destinations — detection is the bottom rung but it is the rung that tells you the upper ones broke.
- An application validates the hostname against an allow-list and then hands the original URL to an HTTP client. What can still go wrong?Two things. The client re-resolves the hostname, so a DNS answer that changed between the check and the connection sends traffic to a different address than the one validated. And if the client follows redirects automatically, the permitted host can redirect to a forbidden one and only the first hop was ever checked. The remedy is to resolve once, validate the resolved address, connect to that pinned address, and re-run the check on every redirect.
- Why does SSRF have outsized impact in cloud environments specifically?Because workloads commonly obtain credentials from a link-local instance metadata endpoint reachable only from the instance itself, which makes network position equivalent to identity. A blind fetch from inside the instance can therefore retrieve or act with the workload's own credentials. Requiring an authenticated, session-oriented metadata protocol and scoping the workload identity narrowly both reduce this, as does routing user-influenced fetches through an egress path with no route to the metadata address.
A courier with a building pass. You cannot enter the server room, but you can hand the courier an envelope addressed to it — the pass belongs to the courier, and the address came from you. Vetting envelopes by address is endless; a fixed list of rooms the courier is allowed to visit is not.
saying these in an interview costs you the question
- Rating blind SSRF as low risk because the response body is not shown to the user
- Filtering the URL string rather than the resolved destination address
- Leaving automatic redirect following on and checking only the first hop
- Assuming a deny-list of private CIDR ranges is sufficient
- Believing internal services are safe because they are 'not exposed to the internet'