Server-side request forgery
classMaking the server issue an HTTP request you control, to somewhere it can reach and you cannot.
01Does it fetch, and do you see the result?
Two questions, and the second decides how pleasant the rest of this is.
Start with a URL whose response you would recognise. If the fetched body is rendered back to you, the SSRF is in-band — you can read internal services directly instead of inferring them a bit at a time.
Read the error, not just the body. "Connection refused" on 8080 and "timed out" on 9090 is a working port scanner. A distinct error per port is nearly as useful as reading the response.
02Nothing reflected — confirm out-of-band
A DNS hit with no HTTP hit means something resolved the name and then refused the connection — usually an egress filter rather than the application. That distinction decides what you try next, so check your collaborator's DNS and HTTP tabs separately.
03Reaching localhost
The blocklist is almost always string matching, not resolution.
@ is userinfo. A naive parser reads the wrong host.The reliable defence is resolve-then-check-the-IP. If the application is doing that, none of the above will help and you should look for a redirect instead.
04Redirect chains
Let a server you control do the talking.
Check whether the fetcher follows redirects at all before building this. Some do on Location, some only on meta-refresh, some not at all.
05Cloud metadata
The usual reason SSRF is worth reporting as critical.
Metadata-Flavor: Google, so you need header control too.Metadata: true.If the target is on IMDSv2 and you cannot set headers, say so in the report rather than claiming credentials are exposed. The finding is still real — it's just not that finding.
06Other schemes
When the fetcher isn't limited to HTTP.
file:// is the fastest way to prove the fetcher is unrestricted, and it is much easier to explain in a report than a gopher payload.