SSRF Attacks Explained: How Attackers Reach Your Internal Network via Your App
What is SSRF?
Server-Side Request Forgery (SSRF) is a vulnerability where an attacker can make a server-side application send HTTP requests to an arbitrary destination — including internal services, cloud metadata endpoints, and other systems that should never be accessible from the internet.
SSRF was added to the OWASP Top 10 in 2021 as A10: Server-Side Request Forgery. It's one of the fastest-growing vulnerability categories, driven by cloud adoption and microservice architectures.
How SSRF Works
1. Attacker → Your App: "Fetch this URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/"
2. Your App → Cloud Metadata API: Fetches the URL (server-side)
3. Cloud Metadata → Your App: Returns IAM credentials
4. Your App → Attacker: Forwards the response containing AWS keys
The key insight: your server trusts itself. Internal services, cloud metadata APIs, and admin panels that block external requests happily respond to requests from your own server.
Real-World SSRF Breaches
Capital One (2019) — $80M Fine, 100M Records
The attacker exploited an SSRF vulnerability in a WAF (Web Application Firewall) to access AWS metadata at 169.254.169.254, obtained IAM role credentials, and used them to exfiltrate 100+ million customer records from S3.
Attack chain:
- SSRF to
http://169.254.169.254/latest/meta-data/iam/security-credentials/ - Retrieved temporary AWS credentials
- Used
aws s3 syncto download all customer data - 100M credit card applications, 140,000 SSNs, 80,000 bank account numbers
GitLab (2021) — Critical SSRF
GitLab's import feature allowed users to specify a URL to import a project from. The URL wasn't properly validated, allowing attackers to:
- Access internal GitLab services
- Read AWS/GCP metadata
- Scan internal network ports
Common SSRF Patterns
Pattern 1: URL Preview / Link Unfurling
// Slack-style link preview
app.post('/api/preview', async (req, res) => {
const { url } = req.body;
const response = await fetch(url); // SSRF!
const html = await response.text();
const title = html.match(/<title>(.*?)<\/title>/)?.[1];
res.json({ title, url });
});
Pattern 2: Webhook / Callback URLs
// Payment webhook
app.post('/api/webhooks/configure', async (req, res) => {
const { callbackUrl } = req.body;
// Attacker sets callbackUrl to http://169.254.169.254/...
await fetch(callbackUrl, { method: 'POST', body: testPayload }); // SSRF!
});
Pattern 3: Image / File Processing
// Image resizer that fetches from URL
app.post('/api/resize', async (req, res) => {
const { imageUrl, width, height } = req.body;
const image = await fetch(imageUrl); // SSRF!
const buffer = await image.buffer();
const resized = await sharp(buffer).resize(width, height).toBuffer();
res.send(resized);
});
Pattern 4: PDF Generation
// HTML-to-PDF with server-side rendering
app.post('/api/generate-pdf', async (req, res) => {
const { htmlUrl } = req.body;
// Puppeteer navigates to the URL server-side
await page.goto(htmlUrl); // SSRF!
const pdf = await page.pdf();
res.send(pdf);
});
SSRF Defense in Depth
Layer 1: URL Validation
const { URL } = require('url');
const dns = require('dns').promises;
const net = require('net');
async function isSafeUrl(urlString) {
let parsed;
try {
parsed = new URL(urlString);
} catch {
return false;
}
// Block non-HTTP protocols
if (!['http:', 'https:'].includes(parsed.protocol)) return false;
// Block known dangerous hostnames
const blocked = ['localhost', '127.0.0.1', '0.0.0.0', '[::1]', 'metadata.google.internal'];
if (blocked.includes(parsed.hostname)) return false;
// Resolve DNS and check actual IP
const addresses = await dns.resolve4(parsed.hostname).catch(() => []);
for (const addr of addresses) {
if (net.isIP(addr) && isPrivateIP(addr)) return false;
}
return true;
}
function isPrivateIP(ip) {
const parts = ip.split('.').map(Number);
return (
parts[0] === 10 ||
parts[0] === 127 ||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
(parts[0] === 192 && parts[1] === 168) ||
(parts[0] === 169 && parts[1] === 254)
);
}
Layer 2: AWS IMDSv2 (Block Metadata SSRF)
# Require IMDSv2 (token-based) on all EC2 instances
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890 \
--http-tokens required \
--http-put-response-hop-limit 1
Layer 3: Network Segmentation
- Run user-facing applications in a VPC with no direct access to internal services
- Use security groups to block outbound connections to metadata endpoints
- Use a proxy/gateway for all outbound requests with URL allowlisting
Layer 4: Response Validation
Even if an SSRF request succeeds, don't return the raw response:
// Only return specific, expected fields
const response = await safeFetch(url);
const data = await response.json();
res.json({
title: typeof data.title === 'string' ? data.title.slice(0, 200) : '',
description: typeof data.description === 'string' ? data.description.slice(0, 500) : '',
});
SSRF Testing Checklist
| Test | Method |
|---|---|
| Cloud metadata | Try http://169.254.169.254/latest/meta-data/ (AWS), http://metadata.google.internal/ (GCP) |
| Internal services | Try http://localhost:PORT for common ports (3000, 5432, 6379, 8080) |
| DNS rebinding | Register a domain that alternates between public and private IPs |
| Protocol smuggling | Try file:///etc/passwd, gopher://, dict:// |
| Redirect bypass | Host a URL that 302-redirects to http://169.254.169.254/ |
How We Help
Our penetration testing and code review services include comprehensive SSRF testing. We check every server-side URL fetch, webhook handler, and external integration for SSRF vulnerabilities.
Advertisement
Free Security Tools
Try our tools now
Expert Services
Get professional help
OWASP Top 10
Learn the top risks
Related Articles
OWASP Top 10 2025: What's Changed and How to Prepare
A comprehensive breakdown of the latest OWASP Top 10 vulnerabilities and actionable steps to secure your applications against them.
The Ultimate Secure Code Review Checklist for 2025
A comprehensive, actionable checklist for conducting secure code reviews. Covers input validation, authentication, authorization, cryptography, error handling, and CI/CD integration with real-world examples.
Cloud Security Guide: AWS, Azure & GCP Misconfigurations 2025
Master cloud security with comprehensive guides on S3 bucket security, IAM policies, secrets management, and real breach case studies.