Server-Side Request Forgery via API Parameter Injection
Attackers exploit URL parameters to turn your server into a proxy for stealing cloud credentials.

Server-side request forgery, or SSRF, turns a normal feature of your application against you: the server fetches a web resource on your behalf, and an attacker finds a way to decide what that resource actually is. When an application takes a URL from user input and passes it along without checking where it actually points, the server no longer fetches things only for its own users; it fetches whatever an attacker directs it to, acting as the attacker's proxy. Nothing looks broken from the outside. The request still fires, the server still responds, but now it's heading somewhere the attacker chose, not somewhere the developer intended.
That's the whole danger packed into one sentence, and it's why SSRF sits on the official OWASP API Security Top 10 as API7:2023, and carries its own entry in MITRE's catalog of weaknesses as CWE-918. A vulnerability doesn't earn a spot on that list by accident or by being rare. It earns that spot by showing up again across different companies, different codebases, and different years, because teams keep building the same kind of fetch-this-URL feature without checking what "this URL" is actually allowed to be.
Injectable URL Fields in a Modern SaaS API
Most founders picture SSRF as a problem confined to a stray ?url= parameter in a query string, something a developer could spot and fix in an afternoon. The real surface is wider than that, because any field the server uses to go fetch something on the internet counts, and SaaS products add more of these fields every time they ship an integration.
Start with the obvious ones: parameters named ?url=, ?redirect=, ?src=, ?dest=, ?uri=, ?domain=, or ?path= are the classic candidates, and they show up constantly in redirect logic, image loaders, and link-sharing features. Webhook configuration is another major source. GitHub, GitLab, and Slack have all shipped products where a webhook URL field became an SSRF path, and any custom webhook field your own product offers customers carries the same risk by construction. "Import from URL" buttons, RSS feed inputs, and avatar or profile image fields all ask the server to go fetch something from an address the user supplies, which is exactly the pattern SSRF depends on. PDF and report generators deserve a close look too: HTML-to-PDF renderers, invoice generators, and certificate generators often fetch linked resources during rendering, and that fetch step is rarely validated with the same care as a public-facing form. Authentication plumbing adds more entry points still, through OAuth callback URLs, SAML endpoints, and OpenID configuration endpoints, each of which tells the server to go talk to an address supplied somewhere upstream in the flow. The newest category comes from AI integrations: the OWASP MCP Security Cheat Sheet warns that MCP tools which fetch URLs based on LLM-generated parameters can be manipulated through prompt injection to reach internal services, and scans across live MCP servers have found more than a third vulnerable to SSRF.
The same handful of function calls, the actual sinks where the outbound request gets made, underlies all of these features. In PHP that's file_get_contents(), curl_exec(), or fopen(). get() or urllib.request.urlopen(). In Node.js it's fetch(), http.request(), or axios.get(). openConnection() or HttpClient.send(). The feature on the front end can look completely different, a webhook form, an avatar uploader, a PDF export button, but at the code level it's the same kind of call doing the same kind of work. Every new integration a SaaS product ships adds more of these calls, so the count of exploitable entry points tends to grow right alongside the product's own feature list.
How the server's fetch of an internal URL becomes cloud credential theft
The Capital One breach in 2019 shows this chain playing out against a real target. An SSRF vulnerability, combined with other misconfigurations, let an attacker exfiltrate many gigabytes of sensitive financial data out of cloud storage buckets. That breach is the reason security teams stopped treating SSRF as a minor information-disclosure issue and started treating it as a path straight to the cloud account itself.
The chain starts small: an attacker finds a URL-accepting parameter, something like ?url= on a webhook or image-fetch endpoint, and swaps in an internal address where the application expected an external one. From that point, the server makes the next request from inside its own network, using its own position behind the firewall. That single fact is what makes the attack work: the server can reach internal admin panels, localhost services, and private IP ranges that reject any request coming straight from the public internet, because those services were built to trust anything that already lives inside the network.
Picture the vulnerable code for a second. A ?url= parameter gets read from the request and handed straight to fopen(), no check on the domain, no check on the IP range, and whatever comes back gets printed to the browser. That's the entire bug. No filter stands between the user's input and the server's outbound call, so the server will fetch and return anything the attacker asks for.
With that access established, the attacker doesn't stop at an internal admin panel. The next move is to point the same fetch at the cloud metadata service, the special address AWS instances use internally to retrieve their own configuration and credentials. That metadata service is reachable only from inside the instance itself, never from the public internet, at a specific link-local address; it was built without demanding a login because of that isolation. The metadata endpoint, when reached, hands back temporary IAM credentials tied to the instance's role: an access key ID, a secret access key, and a session token. Those three values are all an attacker needs. With them in hand, the attacker authenticates directly to AWS's own APIs, reading S3 buckets, invoking Lambda functions, or looking for a path to escalate privileges further, all of it happening outside the application that got exploited.
The real end result of an SSRF chain is a set of valid, authenticated credentials to the victim's own cloud account, which puts SSRF in a different category of impact than a typical information-disclosure bug.
Why IMDSv2 reduces risk without closing the chain
Anyone who knows AWS well enough will ask the obvious question at this point: doesn't IMDSv2 already fix this? It does meaningfully raise the difficulty, and that matters, but it doesn't end the problem.
IMDSv2 added a token-acquisition step: before any metadata GET request returns sensitive data, the caller has to first make a PUT request to obtain a session token. IMDSv2 also rejects requests carrying forwarded or proxy headers. Those two changes defeat the simplest version of the attack, the one where the attacker's GET request gets forwarded straight through to the metadata endpoint with no extra steps. For a basic, naive SSRF exploit, that's a real wall.
It's not an unbreakable one. DNS rebinding can get an attacker-controlled domain to pass initial validation and then resolve to the metadata address afterward. URL encoding and decimal IP notation can represent the metadata address in a form that slips past a filter written to only catch the obvious string. Redirect chains let the attacker point the fetch at a URL under their own control that then issues a 301 or 302 redirect straight to the metadata address. Differences in how a validation layer parses a URL compared to how the underlying HTTP library parses the same string can open a gap wide enough to exploit. And plenty of environments haven't actually enforced IMDSv2 exclusively. Where IMDSv1 fallback is still permitted, the simpler, original attack chain still works exactly as it did before IMDSv2 existed.
Multi-cloud setups add another wrinkle. Azure's metadata service and Google Cloud's metadata service both use the same address, 169.254.169.254, that AWS uses, but each has its own path structure and its own quirks. Exploiting SSRF against a multi-cloud environment means knowing which metadata service is actually reachable from that particular server, not just assuming the AWS address is the only one that matters.
The conclusion for an engineering team to hold onto is straightforward: IMDSv2 enforcement belongs in the stack as a real, necessary layer of defense, but it's not a stand-in for fixing the underlying SSRF vulnerability. A tester who checks that IMDSv2 is turned on and calls the assessment finished has stopped one step short of actually completing it.
Detecting SSRF via parameter injection in practice
SSRF lives in runtime behavior, in how a deployed application actually responds when it receives a particular input, not in whether a certain function name appears somewhere in the source. That single fact rules out static analysis as a reliable way to find it on its own.
The technique that actually works is out-of-band testing. A tester sets up a listener they control, then supplies a URL pointing at that listener across every URL-accepting parameter, every webhook field, every import feature the application exposes. Then they watch the listener. If a request shows up there, that's proof the server made the outbound call, and proof beats inference every time. This method catches blind SSRF too, the cases where the application's own response gives the attacker nothing to look at, because the confirmation doesn't depend on what the app shows back. It depends on what arrives at the listener.
Automated DAST tools have a role here: they can inject payloads into URL parameters at scale and watch for anomalies in the responses, which gives useful coverage across a large application quickly. What they can't do is replace a tester who understands how the application is built and can connect one finding to the next, building the kind of chain that turns a flagged parameter into a documented account compromise.
Three distinct patterns of SSRF call for three different detection approaches. Full-response SSRF hands the fetched content straight back to the caller, so the tester can see the internal response directly in the application's own output. Blind SSRF makes the request but returns nothing useful in the response, so confirming it depends entirely on that out-of-band listener. Semi-blind SSRF sits between the two, leaking information through error messages or through timing differences that reveal whether the internal request actually succeeded, even without returning its content.
The API testing methodology that StackHawk documents for authorization failures draws the same line that matters here for SSRF: detecting a possible issue and verifying it are two different jobs, and a finding only becomes real once the tester demonstrates the actual behavior. Scanning for suspicious strings in a parameter name won't surface a working SSRF exploit, just as it won't surface a broken object-level authorization flaw. Whitebox access, meaning knowledge of which parameters feed which sink functions and which internal services are reachable from the application's own network position, lets a tester skip past guesswork and go straight at the highest-risk entry points, proving actual impact.
Why compliance-only pen tests miss SSRF
A compliance-grade penetration test and a genuinely thorough one can both produce a signed report, but the two documents can describe very different levels of actual security. A compliance-focused test satisfies an auditor's checklist with the minimum effort needed to pass. A real test traces what an attacker could actually accomplish, through a documented chain of findings that connects one weakness to the next.
SSRF exposes that gap sharply, for two structural reasons. First, it's a context-dependent vulnerability. A tester who doesn't already know which endpoints accept URL inputs, which of those are backed by server-side fetch calls, and which internal services the server can reach will spend most of the engagement window just mapping the application, with little time left to actually exploit anything. Second, the impact only becomes provable through chaining. A scan result reading "this parameter may accept arbitrary URLs" isn't a finding. A finding is a confirmed request that reached the metadata endpoint and came back with usable credentials, documented as a clear path from the original injection point to cloud account access.
Access to source code, cloud configuration, and architecture documentation changes the math. Whitebox access compresses the reconnaissance phase down to a fraction of the time it would otherwise take, freeing the rest of the engagement window for finding and proving impact. That's the structural reason whitebox testing surfaces vulnerabilities like SSRF at a different rate than blackbox testing of the same application.
None of this is an argument against compliance requirements, and a rigorous test should satisfy both goals at once: it checks the boxes an auditor needs while also tracing the chains an attacker would actually follow. An annual, point-in-time test that comes back without an SSRF finding doesn't mean the application has no SSRF. It may mean the tester never had the access, the time, or the methodology needed to find it, and a new integration shipped the week after that assessment opens a new injection point the report never had the chance to cover.
A Real SSRF Finding in a Pen Test Report
A technical founder reading a pen test report has a clear standard to check it against. A real SSRF finding is a proven exploit, documented with the exact parameter involved, the exact payload used, the confirmed outbound request, backed by evidence such as an out-of-band listener log or a screenshot of the returned metadata, and the downstream impact that was demonstrated or could clearly be demonstrated from there.
It should name the specific endpoint and parameter where the attack entered, something like a POST /api/webhooks request through a callback_url field. It should describe what the server could reach internally from that position, whatever internal services, admin panels, or network ranges came into view once the first request landed. It should state whether IAM credentials, internal service tokens, or other secrets came back from that internal reach. And it should spell out the business impact in concrete terms: what an attacker holding those credentials could actually do, whether that's reading data out of S3, invoking functions they shouldn't have access to, or using that foothold to move further into other systems.
What a real finding does not look like is a line item reading "SSRF: possible" with a severity score attached and nothing else. A list of parameter names that "might" accept arbitrary URLs is a lead for further work, not a finding on its own. A vendor who ran a scanner and called it a day produces one document; a vendor who traced the chain from the first injectable field all the way to the credentials at the end of it produces another.


