Back

C10: Stop Server-Side Request Forgery - Overview

What is this control?

Stop Server-Side Request Forgery (SSRF) is the proactive control of making sure that when your server fetches a URL, it can only ever reach destinations you intended—never an internal service, a cloud metadata endpoint, or a local file. SSRF happens when an attacker supplies or influences a URL that the application then requests on its behalf, turning your trusted server into a proxy that speaks from inside your network. This control is the set of defenses that closes that door.

The vulnerability is Server-Side Request Forgery; this page is the defense that stops it. The distinction matters: the risk is "my server can be tricked into making a request I did not intend"; the control is "every outbound request my server makes is validated against an allow-list, resolved and re-checked at the IP level, and confined by the network so it physically cannot reach anything sensitive."

Note on taxonomy: In the 2021 OWASP Top 10, SSRF was its own category (A10). In the 2025 web Top 10 it has been folded into Broken Access Control rather than standing alone. It nonetheless remains a distinct, first-class item in the OWASP Top 10 Proactive Controls (C10, 2024) because stopping it is a specific engineering discipline—how you handle outbound URLs—that developers need to implement deliberately.

Core Concept

Unsafe outbound request (attacker controls where the server goes):
  Input        -> user-supplied URL used verbatim
  Validation   -> none, or a block-list of "bad" strings
  DNS          -> resolved once, only the hostname is checked
  Schemes      -> http, https, file, gopher, dict all allowed
  Redirects    -> followed blindly to wherever they point
  Network      -> app can reach 127.0.0.1, 169.254.169.254, 10.0.0.0/8
  Response     -> raw body reflected back to the caller

Safe outbound request (this control applied):
  Input        -> parsed, then matched against an allow-list
  Validation   -> allow-list of scheme + host + port (deny by default)
  DNS          -> resolved, and the RESOLVED IP is checked and pinned
  Schemes      -> only http/https; file/gopher/dict disabled
  Redirects    -> not followed, or every hop re-validated
  Network      -> egress filtering blocks private/link-local ranges
  Response     -> size-limited, never reflected raw to the caller

Why validating the hostname is not enough

The single most important idea in this control is that a URL is not safe just because its hostname looked safe. An attacker who owns a domain can point it at 127.0.0.1 or 169.254.169.254, and can change that answer between the moment you validate it and the moment your HTTP client connects (DNS rebinding). The defense therefore validates on the resolved IP address, re-resolves and pins that address for the actual connection, and rejects any address that falls in a private, loopback, link-local, or reserved range.

Why This Control Matters

Business Impact of Getting It Right

Technical Impact

Core Practices

Stopping SSRF is a layered discipline; no single check is sufficient. The reinforcing practices are:

Where SSRF-Prone Requests Live

SSRF lives anywhere your server takes a URL (or something that becomes a URL) from a user and fetches it. Common features to audit:

FeatureWhy it fetches a URLSSRF risk
WebhooksPosts events to a customer-supplied callback URLCallback pointed at internal/metadata endpoints
Link previews / unfurlingFetches a pasted link to render a cardAny URL a user pastes is fetched server-side
Importers"Import from URL" for files, feeds, or dataURL resolved and downloaded by the server
PDF / image / thumbnail generatorsFetches remote assets to renderEmbedded URLs pull internal resources
Document / HTML convertersFollows <img>, CSS, and asset URLsMarkup smuggles internal requests
Proxies / gatewaysForward requests to a target URLTarget is directly attacker-controlled
Integrations / OAuth discoveryFetches config or JWKS from a provided base URLDiscovery URL steers the server inward

Real-World Incident Classes

These are recurring classes of SSRF incident that this control is designed to prevent, described as patterns rather than specific vulnerabilities.

Class 1: Cloud metadata credential theft

By far the most damaging SSRF class. A user-influenced fetch is steered to a cloud instance metadata service at the link-local address 169.254.169.254. On configurations that expose credentials without a session token, the attacker retrieves the instance role's temporary keys and uses them against the cloud account. The industry response—session-token-based metadata services (IMDSv2) and mandatory hop limits—exists precisely because of this incident class. Blocking the metadata IP by network egress policy and requiring IMDSv2 closes it.

Class 2: Reaching internal-only services

SSRF is used to request internal admin consoles, databases, caches, and orchestration APIs that were never exposed to the internet but are reachable from the application host. Because the request originates from a trusted internal source, network ACLs and "internal is safe" assumptions do not stop it.

Class 3: Internal reconnaissance and port scanning

Even without reading a response, differences in timing and error behaviour let an attacker enumerate live hosts and open ports inside the network, mapping the environment for a later attack.

Class 4: Local file and protocol abuse

Where the HTTP client honors extra schemes, file:// reads local files and gopher:///dict:// smuggle crafted bytes to line-based internal services. Restricting schemes to http/https removes this class entirely.

Common Misunderstandings

Myth 1: "I validated the hostname, so it's safe"

Reality: hostnames resolve to IPs that the attacker may control and can change after your check. Validate the resolved IP and pin it for the connection; a hostname allow-list alone is bypassed by DNS rebinding.

Myth 2: "A block-list of 127.0.0.1 and localhost is enough"

Reality: block-lists are endlessly bypassable—127.0.0.1 also appears as 127.1, 2130706433 (decimal), 0x7f000001 (hex), IPv6 [::1] and [::ffff:127.0.0.1], and DNS names that resolve to loopback. Allow-list what is permitted instead.

Myth 3: "It's an internal request, so there's nothing to steal"

Reality: the internal network is exactly where the crown jewels live—metadata endpoints, databases, and admin planes. "Internal" is the target, not a mitigation.

Myth 4: "Following redirects is fine, the first URL was checked"

Reality: a validated URL can redirect (301/302) to http://169.254.169.254/ or a private IP. Do not follow redirects for user-supplied fetches, or re-validate every hop as strictly as the first.

Myth 5: "A WAF or URL-string filter will catch it"

Reality: string filtering cannot account for every IP encoding, scheme, and DNS trick. The reliable control is IP-level validation after resolution plus network egress filtering—defense in depth, not a regex.

How This Control Relates to SSRF (the risk)

AspectServer-Side Request Forgery (the risk)Stop SSRF (the control)
NatureServer tricked into an unintended requestEvery outbound request is validated and confined
Default postureFetches wherever the URL pointsDeny by default; allow-listed destinations only
Where enforcedAbsent—URL used verbatimApp validation + resolved-IP check + network egress
Failure modeMetadata theft, internal access, file readExplicit, reviewed exception to the allow-list

Key Takeaways

  1. The control is about outbound requests—wherever your server fetches a user-influenced URL, it must be constrained.
  2. Allow-list, never block-list—permit specific schemes, hosts, and ports; deny everything else.
  3. Check the resolved IP and pin it—defeat DNS rebinding by validating and connecting to the same address.
  4. Defense in depth—app validation, disabled schemes, no redirects, network egress filtering, and IMDSv2 together.
  5. SSRF moved under Broken Access Control in 2025, but the defense is still a distinct discipline you implement in code and infrastructure.

Self-Assessment Checklist

Next Steps