Description
Server-side request forgery occurs when an application fetches a remote resource based on a URL supplied or influenced by the user, without adequately restricting what destinations can be reached. The server acts as a proxy — and since requests originate from inside the network, they can reach services that are blocked from the public internet.
SSRF has become one of the most critical vulnerability classes in cloud environments. AWS, GCP, and Azure all expose a metadata endpoint at http://169.254.169.254/ that returns IAM credentials and instance configuration — and that endpoint is reachable from inside every cloud instance.
How It Works
A document conversion feature accepts a URL to fetch:
POST /api/convert
{"url": "https://user-supplied-domain.com/document.pdf"}
The attacker changes the URL to the AWS metadata endpoint:
POST /api/convert
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
The server fetches the URL internally and may return the response in an error message, in the converted output, or through a timing side channel. The attacker now has a list of IAM role names attached to the instance. A second request retrieves the temporary credentials:
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/production-role"}
With those credentials, the attacker has the same AWS permissions as the application itself.
Impact
- Cloud credential theft — retrieve IAM credentials from metadata endpoints and pivot to the full cloud environment.
- Internal service access — reach databases, Kubernetes APIs, Consul, Vault, Elasticsearch, and other services that assume internal traffic is trusted.
- Data exfiltration — read internal configuration files, secrets, and environment variables.
- Remote code execution — interact with services that execute commands (Redis, Memcached, internal admin panels).
- Port scanning — map the internal network by timing or error-based responses to different hosts and ports.
Detection
- Identify all URL-fetching features — explicit URL parameters, webhook registration, import from URL, image/document fetching, link previews.
- Test for internal access — submit
http://localhost/,http://127.0.0.1/,http://169.254.169.254/(cloud metadata),http://192.168.1.1/, andhttp://[::1]/. - Test for DNS-based SSRF — use an out-of-band DNS callback to confirm that DNS resolution occurs even when HTTP responses are not reflected.
- Test URL parsers — different URL parsers handle edge cases differently. Try:
http://attacker.com@169.254.169.254/,http://169.254.169.254#.attacker.com,http://0x7f000001/(hex-encoded localhost). - Check for redirect following — even if the application validates the initial URL, a redirect from a trusted domain to an internal address may bypass the check.
Remediation
Allowlist outbound destinations. If the application only needs to fetch resources from a specific domain or set of domains, enforce that restriction explicitly. Deny everything else.
Block internal ranges at the network layer. Configure egress firewall rules to prevent the application server from reaching RFC 1918 addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local addresses (169.254.0.0/16), and loopback.
Resolve and re-validate after DNS. Validate both the URL and the resolved IP address. Reject requests where the resolved IP falls in a blocked range. Be aware of DNS rebinding — re-resolve immediately before making the request.
Disable unnecessary URL schemes. If the application only needs to fetch HTTPS resources, reject file://, dict://, gopher://, ftp://, and http:// (without TLS).
