← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Server-Side Request Forgery (SSRF)

Security CWE-918 OWASP A10:2021 CVSS 8.6 PHP 5.0+ Advanced
debt(d7/e5/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints list semgrep and psalm, which are specialist SAST tools that can catch the basic pattern of curl_exec/file_get_contents with user-supplied input. However, sophisticated bypasses like DNS rebinding, alternate URL schemes (gopher://, file://), and post-resolution IP validation failures are not reliably caught by static analysis alone — runtime testing or manual review is required for those. This places it above d5 (specialist tool) but not quite d9 (silent in production), landing at d7.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to validate and allowlist target URLs server-side, but common_mistakes reveal that a complete fix requires: blocking private IP ranges after DNS resolution, preventing DNS rebinding (re-checking IP at connection time), blocking dangerous schemes (file://, gopher://, dict://), and replacing raw user-supplied URLs throughout the codebase. This is more than a single-line patch or simple parameter swap — it requires implementing a dedicated URL validation layer that must be applied consistently across all fetch points.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to scope is web and CLI contexts, and the fix primarily involves adding URL validation logic around fetch operations. While it must be applied consistently wherever user-supplied URLs are used, it does not impose a cross-cutting architectural burden on the entire codebase — it's scoped to components that make outbound HTTP requests. It's slightly above b1 (single utility function) because the validation must be consistently applied across those fetch points.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception field explicitly states: 'SSRF is only dangerous if the server can reach the internet' — when in fact it is most dangerous for reaching internal services that are otherwise unreachable from the outside. This is a documented, serious cognitive trap: developers assume blocking public internet access is sufficient protection, but the real attack surface (cloud metadata at 169.254.169.254, internal admin panels, local databases) is invisible until exploited. DNS rebinding bypass also contradicts the intuitive belief that hostname validation is sufficient.

About DEBT scoring →

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

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();
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 74
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 2 pings S 4 pings S 2 pings M 2 pings T 3 pings W 4 pings T 1 ping F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T 0 pings F 1 ping S 2 pings S 2 pings M 1 ping T 0 pings W
No pings yet today
Google 1
Scrapy 11 Perplexity 10 Amazonbot 9 Google 9 SEMrush 6 ChatGPT 4 Ahrefs 4 Sogou 3 Bing 2 PetalBot 2 Unknown AI 1 Claude 1 Meta AI 1
crawler 58 crawler_json 3 pre-tracking 2
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


✓ schema.org compliant