Server-Side Request Forgery (SSRF)
Also Known As
Server-Side Request Forgery
SSRF attack
internal request forgery
TL;DR
The server is tricked into making HTTP requests to internal or unintended destinations on behalf of the attacker.
Explanation
SSRF allows attackers to make the server issue requests to arbitrary URLs — including internal services (cloud metadata endpoints, databases, admin interfaces) not exposed to the public internet. In cloud environments, SSRF against 169.254.169.254 can expose IAM credentials. Mitigation: validate and allowlist target URLs, block private IP ranges, reject non-http(s) schemes, and prefer dedicated HTTP client libraries with configurable restrictions.
How It's Exploited
POST webhook_url=http://169.254.169.254/latest/meta-data/
# AWS metadata endpoint — returns instance credentials
POST webhook_url=http://internal-admin.corp/secret
# AWS metadata endpoint — returns instance credentials
POST webhook_url=http://internal-admin.corp/secret
Diagram
flowchart TD
ATK[Attacker] -->|fetch http://internal-api/secret| APP[Vulnerable App<br/>fetch URL param]
APP -->|request from server| INT[Internal API<br/>192.168.1.100]
APP -->|request from server| META[AWS Metadata<br/>169.254.169.254]
INT & META -->|sensitive data| APP --> ATK
subgraph Fix
ALLOW[Allowlist external URLs<br/>Block internal IP ranges<br/>169.254/10.x/172.16/192.168]
end
style FIX fill:#238636,color:#fff
style INT fill:#f85149,color:#fff
style META fill:#f85149,color:#fff
Common Misconception
✗ SSRF is only dangerous if the server can reach the internet. SSRF is most dangerous for reaching internal services — cloud metadata endpoints (169.254.169.254), internal admin panels, and databases that are unreachable from the outside.
Why It Matters
SSRF turns your server into a proxy to attack internal services — cloud metadata endpoints, internal databases, and services on 127.0.0.1 that are unreachable from the internet.
Common Mistakes
- Fetching user-supplied URLs with curl_exec() or file_get_contents() without validating the resolved IP.
- DNS rebinding bypass: validating the hostname but not re-checking the IP at connection time.
- Not blocking private IP ranges (10.x, 172.16.x, 192.168.x, 127.x, 169.254.x) after DNS resolution.
- Allowing file://, gopher://, or dict:// URL schemes alongside http://
Code Examples
✗ Vulnerable
\$url = \$_POST['webhook_url'];
\$resp = file_get_contents(\$url); // SSRF — attacker controls the URL
✓ Fixed
function safeRequest(string \$url): string {
\$parsed = parse_url(\$url);
// Only allow HTTPS to public internet
if (\$parsed['scheme'] !== 'https') throw new \InvalidArgumentException('HTTPS required');
// Block private/internal IP ranges
\$ip = gethostbyname(\$parsed['host']);
if (filter_var(\$ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
throw new \InvalidArgumentException('Private/reserved IP not allowed');
}
return (new GuzzleHttp\Client())->get(\$url)->getBody()->getContents();
}
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
29
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
Amazonbot 9
Perplexity 7
SEMrush 3
Google 2
Ahrefs 2
ChatGPT 1
Unknown AI 1
Also referenced
How they use it
crawler 22
crawler_json 1
pre-tracking 2
Related categories
⚡
DEV INTEL
Tools & Severity
🔴 Critical
⚙ Fix effort: Medium
⚡ Quick Fix
Validate and allowlist target URLs server-side; never forward raw user-supplied URLs to curl/file_get_contents
📦 Applies To
PHP 5.0+
web
cli
🔗 Prerequisites
🔍 Detection Hints
curl_exec or file_get_contents or fopen with $_GET/$_POST URL parameter
Auto-detectable:
✓ Yes
semgrep
psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Medium
✗ Manual fix
Fix: High
Context: Function
Tests: Update
CWE-918