
Server-Side Request Forgery consistently ranks in the OWASP Top 10 because the attack surface keeps expanding. Every new cloud service, every internal API, every webhook integration adds a potential SSRF target. The endpoint that makes SSRF consistently devastating in cloud environments is 169.254.169.254 — the link-local metadata service address used by AWS EC2, Google Cloud, Azure, and most other major cloud platforms. An SSRF that reaches this endpoint extracts IAM credentials, and from there the blast radius is limited only by the attached IAM role.
This post covers the mechanics of how SSRF reaches the metadata service, the bypass techniques that defeat input validation, and why runtime-layer detection is the only approach that catches all attack paths.
What the Metadata Service Exposes
AWS's Instance Metadata Service (IMDS) at http://169.254.169.254/latest/meta-data/ returns information about the EC2 instance — instance ID, region, network interfaces, security groups, and most critically, IAM credentials. A request to http://169.254.169.254/latest/meta-data/iam/security-credentials/my-role returns a JSON object containing AccessKeyId, SecretAccessKey, and Token. These credentials are valid for up to 6 hours and carry the full permissions of the attached IAM role.
The Capital One data breach in 2019 exploited exactly this path. A misconfigured WAF running on an EC2 instance was used as an SSRF relay to access the metadata service, extract credentials for an S3 bucket listing role, and enumerate and download 106 million customer records. The IAM role had excessive permissions relative to what the application actually needed — a common configuration mistake that the metadata SSRF turned into a catastrophic breach.
The Basic SSRF Pattern
SSRF exploits features that allow users to specify URLs the server should fetch. PDF generators that accept a URL to convert, image processors that fetch remote images, webhook testers that ping user-specified URLs, URL preview features in messaging platforms — all of these are SSRF candidates if they fetch arbitrary URLs without validation.
The basic attack: a user submits a URL pointing to the metadata service instead of a legitimate external resource. The server fetches the URL, receives the metadata response, and either returns it directly or stores it somewhere the attacker can access.
Input validation defenses check whether the submitted URL is a private or link-local address before making the request. If the URL contains 169.254.169.254 or resolves to a private range (10.x, 172.16-31.x, 192.168.x), the request is blocked. This sounds effective. It is not, for several reasons.
DNS Rebinding
An attacker registers a domain they control, say ssrf-rebind.attacker.com. The application checks whether this hostname resolves to a blocked address — during the check, the DNS resolution returns a legitimate public IP like 1.2.3.4. The check passes. The application then makes the HTTP request to the same hostname. This time, the attacker's DNS server returns 169.254.169.254 instead. The HTTP request goes to the metadata service.
This attack works because the validation and the request use two separate DNS lookups. The time window between them — typically just milliseconds — is sufficient for an attacker who controls their DNS server's TTL to serve different addresses. The fix is to validate the resolved IP address at request time (at the socket level), not at the URL parsing step. Most input validation implementations do not do this correctly.
URL Encoding and Parser Confusion
URL parsing is inconsistent across libraries. Bypasses that work against one URL parser may not work against another, but the variety is large. Some examples that have successfully bypassed validation in documented bug bounty reports:
http://[::ffff:169.254.169.254]/— IPv6 representation of an IPv4 addresshttp://169.254.169.254.nip.io/— wildcard DNS service that resolves to the embedded IPhttp://0xa9fea9fe/— hexadecimal encoding of 169.254.169.254http://2852039166/— decimal integer encoding of the same addresshttp://169.254.169.254%23.attacker.com/— URL fragment bypass against parsers that split on #
Building a validation function that handles all of these reliably requires deep knowledge of URL parsing edge cases and consistent testing against multiple HTTP client libraries. Most applications do not have this, which is why SSRF defenses based on input validation are fragile.
IMDSv2 Is Not a Complete Defense
AWS introduced IMDSv2 (Instance Metadata Service version 2) in 2019 as a defense against SSRF. IMDSv2 requires a two-step process: first, a PUT request to get a session token, then using that token in subsequent GET requests. Since SSRF typically only allows GET requests (following redirects), the PUT requirement blocks many SSRF paths to the metadata service.
IMDSv2 is a meaningful defense layer, but it does not eliminate SSRF risk entirely. SSRF against internal services other than the metadata endpoint — other EC2 instances, internal load balancers, AWS service endpoints on 169.254.x.x other than IMDS, or internal APIs — is not affected by IMDSv2. SSRF that can issue PUT requests (via HTTP client libraries that follow redirects including cross-method redirects, or applications that make POST/PUT requests based on user-supplied URLs) can still reach IMDSv2. And SSRF on Google Cloud, Azure, and other platforms uses different metadata service paths that IMDSv2 does not protect.
What Runtime Detection Sees
When an application makes an HTTP request to the metadata service as the result of an SSRF attack, that network call originates from the application process. Raven.io's agent instruments outbound network connection attempts at the socket layer. Every outbound connection includes the destination IP and port, the calling code path, and the request context.
During the baseline period, the agent maps which outbound network calls the application legitimately makes. A Java payment service that calls Stripe's API, sends metrics to Datadog, and checks an internal service discovery endpoint — those three destinations are in the baseline. A connection to 169.254.169.254 on port 80 is not in any legitimate application's baseline. It triggers a block and an alert regardless of how the URL was crafted, which DNS rebinding technique was used, or which encoding bypassed the input validator.
This detection approach requires no knowledge of SSRF attack patterns. The metadata service address is simply not in the behavioral baseline, and any deviation from the baseline gets flagged. It closes the gap that URL validation leaves open.
Defense in Depth for SSRF
A complete SSRF defense combines multiple layers. Strict allowlisting of outbound network destinations at the application level — only make HTTP requests to domains on an explicit allowlist — eliminates the attack surface for most applications. For applications that legitimately need to fetch arbitrary URLs (URL preview features, webhook testers), isolation is the answer: run those URL-fetching operations in a separate service with minimal IAM permissions and no network access to internal resources.
IMDSv2 enforcement (requiring IMDSv2 and disabling IMDSv1) reduces SSRF impact specifically for the metadata service path. Network-level blocking of 169.254.169.254 from application subnets adds another layer. None of these controls, individually or together, covers every SSRF path — which is why runtime detection of outbound connections that deviate from the behavioral baseline is the defense layer that catches what the others miss.
The metadata service SSRF will keep appearing because the preconditions — applications that fetch user-specified URLs, cloud credentials accessible via link-local addresses — are deeply embedded in how cloud applications are built and deployed. Defending against it requires defense in depth, not a single-point solution.
Block SSRF at the Network Layer
Raven.io's network call monitoring catches outbound requests to metadata services and internal infrastructure that bypass URL validation. See the full list of blocked destinations in the trial dashboard.
Request a Demo