SSRF
Server-Side Request Forgery · /ˌɛsˌɛsɑːrˈɛf/
SSRF is the attack class where an outside user tricks a server into making requests on their behalf, usually to internal infrastructure that's unreachable from the public internet. Any service that fetches a URL provided by user input — including most CORS proxies, webhook validators, and link-preview generators — is a potential SSRF surface.
Why it's dangerous
The attacker's machine can't reach 169.254.169.254 (the AWS metadata service) or 10.0.0.5 (an internal Redis without auth). The server can. If the server will fetch any URL it's given, the attacker just asks it to fetch those internal URLs and returns the result. That's how cloud breaches happen.
Classic targets
- Cloud metadata endpoints —
169.254.169.254on AWS, GCP, Azure. Returns temporary IAM credentials. - Internal admin UIs — Kibana, Elasticsearch, Grafana, internal-only Jenkins, often deployed assuming "only the internal network can reach us".
- Unauthenticated data stores — Redis, Memcached, Mongo bound to
0.0.0.0"for convenience" inside a private network. - Local services —
localhostdebug endpoints, profilers, anything bound to 127.0.0.1. - Side-channel probing — sending many requests and timing the responses to map the internal network.
How a CORS proxy gets weaponized
// Innocent CORS proxy code (DO NOT DEPLOY)
app.get('/proxy', async (req, res) => {
const target = req.query.url;
const upstream = await fetch(target);
res.set('Access-Control-Allow-Origin', '*');
res.send(await upstream.text());
});
// Attacker:
GET /proxy?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
// Server happily fetches AWS creds and returns them.
The standard mitigations
- Resolve hostnames and check the IP against an allowlist or denylist before fetching. The check must happen on the resolved IP, not the hostname —
localtest.meresolves to127.0.0.1. - Reject private and reserved ranges: 10/8, 172.16/12, 192.168/16, 127.0.0.0/8, 169.254.0.0/16, ::1, fc00::/7.
- Reject non-HTTP schemes like
file://,gopher://,data://, which open additional protocol-confusion attacks. - Strip dangerous request headers — never forward incoming
Authorization,Cookie, or proxy-control headers to the upstream. - Limit response size and time so the proxy can't be used as a relay for terabyte exfiltration.
- Rate-limit per account — abuse usually involves many probes; per-IP limits won't catch it but per-key will.
For the corsproxy.dev specifics, see the security writeup.