TL;DR - Key Insights
Figure: High-level SSRF attack surface overview (rendered with Mermaid)
- SSRF allows attackers to make servers fetch data from internal systems
- Cloud metadata services (
169.254.169.254) are prime targets for credential theft - DNS rebinding can bypass naive IP blacklists dynamically
- IP encoding bypasses simple string-based filters
- Defense requires: Resolve → Inspect → Block approach
- Whitelist-based validation is more secure than blacklisting
Understanding SSRF: The Core Vulnerability
Server-Side Request Forgery (SSRF) is a critical web vulnerability that allows attackers to force a server to make unintended HTTP requests to arbitrary destinations. This transforms the compromised server into an unwitting proxy, accessing resources it was never designed to reach.
graph TD
A[Attacker Input<br/>Malicious URL targeting internal resources] --> B[Vulnerable Application<br/>Server processes request without proper validation]
B --> C[Internal Target<br/>Access to metadata services, admin panels, or databases]
C --> D[Data Compromise<br/>Sensitive information exposed to attacker]
Why SSRF Remains Critical
Despite being well-documented, SSRF continues to plague modern applications due to:
- Incomplete protections
- Over-reliance on hostname blacklists
The vulnerability's impact is amplified in cloud environments where it can lead to full infrastructure compromise.
Basic SSRF Exploitation
Typical SSRF Scenario
Example of how a URL preview feature can be exploited for SSRF
# Normal request
GET /preview?url=http://example.com HTTP/1.1
Host: vulnerable.com
# Malicious SSRF payload
GET /preview?url=http://127.0.0.1:8000/admin HTTP/1.1
Host: vulnerable.com
# Result: Server fetches internal admin panel
The vulnerability emerges when applications fail to properly validate or sanitize URL parameters, allowing attackers to redirect server requests to internal services.
Common SSRF Targets
| Risk Level | Target Type | Examples |
|---|---|---|
| HIGH | Localhost Services | Internal applications and admin panels |
| CRITICAL | Cloud Metadata | AWS, GCP, Azure instance metadata |
| MEDIUM | Internal Networks | Private APIs and dashboards |
| HIGH | Backend Services | Redis, Elasticsearch, databases |
| MEDIUM | File Systems | Local file access via file:// protocol |
| LOW | Network Scanning | Port scanning and service discovery |
Cloud Metadata Exploitation
The Goldmine: 169.254.169.254
This special IP address hosts instance metadata services across major cloud providers.
Successful SSRF exploitation here can lead to complete cloud environment compromise through IAM credential theft and configuration exposure.
AWS Metadata Service v1
No Authentication – Direct access to instance metadata and IAM credentials
Endpoint:
http://169.254.169.254/latest/meta-data/
curl -X GET "http://169.254.169.254/latest/meta-data/"
AWS Metadata Service v2 (IMDSv2)
Token Required – Token-based metadata access with additional security
Endpoint:
http://169.254.169.254/latest/api/token
curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
Google Cloud Metadata
Header Required – Access to instance metadata and service account tokens
Endpoint:
http://169.254.169.254/computeMetadata/v1/instance/
curl -X GET "http://169.254.169.254/computeMetadata/v1/instance/" \
-H "Metadata-Flavor: Google"
Azure Instance Metadata
Header Required – Instance configuration and managed identity tokens
Endpoint:
http://169.254.169.254/metadata/instance?api-version=2021-02-01
curl -X GET "http://169.254.169.254/metadata/instance?api-version=2021-02-01" \
-H "Metadata: true"
Advanced Bypass Techniques
| Risk | Technique | Example |
|---|---|---|
| MEDIUM | Decimal Encoding | 2130706433 -> 127.0.0.1 |
| MEDIUM | Hexadecimal Encoding | 0x7f000001 -> 127.0.0.1 |
| MEDIUM | Octal Encoding | 017700000001 -> 127.0.0.1 |
| LOW | URL Encoding | %31%32%37%2e%30%2e%30%2e%31 |
| CRITICAL | DNS Rebinding | evil.com -> 127.0.0.1 (time-based) |
DNS Rebinding: Dynamic Origin Deception
A sophisticated attack that dynamically resolves domain names to internal IP addresses, bypassing simple domain-based filters.
Attack Flow
CRITICAL Bypass Technique:
Attacker controls a domain that initially resolves to a public IP, passes validation, then resolves to169.254.169.254during the actual request.
SSRF Attack Map
%%{init: {"theme":"dark","themeVariables":{"fontSize":"14px","fontFamily":"monospace"},"flowchart":{"defaultRenderer":"elk"}}}%%
flowchart TD
subgraph Legend[" "]
L1["Attack Path"]
L2["Bypass Technique"]
L3["Cloud Target"]
L4["Defense Layer"]
L5["Critical Risk"]
end
A["Attacker Input<br/>Malicious URL"] --> B{"Vulnerable App<br/>Processes URL?"}
B -- Yes --> C1["Localhost Services<br/>(127.0.0.1:8000/admin)"] & C2["Internal Networks<br/>(10.0.0.0/8, 192.168.x.x)"] & C3["Backend Services<br/>(Redis, DB, ES)"] & C4["File System<br/>file://etc/passwd"] & C5["Port Scanning"] & D["Target: 169.254.169.254<br/>Cloud Metadata Service"]
D --> D1["AWS IMDSv1<br/>No Auth"] & D2["AWS IMDSv2<br/>Token Required"] & D3["Google Cloud<br/>Metadata-Flavor: Google"] & D4["Azure IMDS<br/>Metadata: true"]
D1 --> E[["IAM Roles / Service Account Tokens<br/>Full Cloud Compromise"]]
D2 --> E
D3 --> E
D4 --> E
B --> F["Bypass Filters?"]
F -- Decimal --> F1["2130706433 → 127.0.0.1"]
F -- Hex --> F2["0x7f000001 → 127.0.0.1"]
F -- Octal --> F3["017700000001 → 127.0.0.1"]
F -- URL Encode --> F4["%31%32%37%2e%30%2e%30%2e%31"]
F -- DNS Rebinding --> F5[["evil.com → 1.2.3.4<br/>→ 169.254.169.254"]]
G["Defense Strategy: Resolve → Inspect → Block"] --> H1["1. DNS Resolution<br/>Resolve Early & Consistently"] & H2["2. IP Inspection<br/>Block RFC 1918 / 3927 IPs"] & H3["3. URL Whitelisting<br/>Allow Only Known Domains"] & H4["4. Egress Firewall<br/>Block 169.254.169.254"]
H3 --> H3a["Regex + Normalization<br>Parse Host, Path, Port"] & H3b["Log Blocked Requests"] & I{{"Attack Blocked"}}
H4 --> H4a["Default Deny Outbound<br>Allow Only HTTPS:443"] & H4b["Monitor & Alert on Egress"] & I
H1 --> I
H2 --> I
L1:::attack
L2:::bypass
L3:::cloud
L4:::defense
L5:::critical
C1:::attack
C2:::attack
C3:::attack
C4:::attack
C5:::attack
D:::cloud
D1:::cloud
D2:::cloud
D3:::cloud
D4:::cloud
E:::critical
F1:::bypass
F2:::bypass
F3:::bypass
F4:::bypass
F5:::critical
G:::defense
G:::defense
H1:::defense
H1:::defense
H2:::defense
H2:::defense
H3:::defense
H3:::defense
H4:::defense
H4:::defense
H3a:::defense
H3b:::defense
I:::defense
H4a:::defense
H4b:::defense
classDef attack fill:#ff4d4d,stroke:#a00,color:#fff,fontWeight:bold
classDef bypass fill:#ff8c1a,stroke:#cc6600,color:#fff
classDef cloud fill:#3399ff,stroke:#0066cc,color:#fff
classDef defense fill:#2eb82e,stroke:#006400,color:#fff
classDef critical fill:#cc0000,stroke:#800,color:#fff
style Legend fill:none,stroke:none
Comprehensive Defense Strategies
Whitelisting vs Blacklisting
HIGH PRIORITY: Implement strict allowlists of permitted destinations instead of trying to block known bad ones.
Implementation Checklist
- Define specific allowed domains and IP ranges
- Implement regex patterns for permitted URLs
- Regularly review and update whitelist entries
- Log all blocked requests for monitoring
if (!isWhitelisted(url)) {
throw new SecurityException('URL not in allowlist');
}
Blacklists are easily bypassed with encoding and DNS tricks.
Whitelists provide stronger security posture.
DNS Resolution Security
HIGH PRIORITY: Validate both hostname and resolved IP addresses before making requests.
Implementation Checklist
- Resolve DNS before and after URL validation
- Block private IP ranges (RFC 1918, RFC 3927)
- Implement consistent DNS resolution timing
- Use secure DNS resolvers with monitoring
const resolvedIP = await dns.resolve(hostname);
if (isPrivateIP(resolvedIP)) block();
DNS rebinding attacks exploit timing between validation and execution. Resolve consistently.
Network-Level Controls
HIGH PRIORITY: Implement strict egress filtering
Implementation Checklist
- Block access to metadata services
- Restrict outbound connections by default
- Allow only necessary external services
- Monitor and log all egress traffic
Outbound Firewall Rules
Network-level controls provide defense in depth
Application-Level Validation
MEDIUM PRIORITY: Input sanitization and normalization
Implementation Checklist
- Normalize URLs before validation
- Parse and validate each URL component
- Implement timeout controls
- Use dedicated HTTP client libraries
Combine with network controls for comprehensive protection
Secure Your Applications Against SSRF
Follow the golden rule: Resolve → Inspect → Block
- Resolve DNS early and consistently
- Inspect both URL and resolved IP
- Block anything not explicitly allowed
Prevention > Detection — Whitelist everything. Trust nothing.
By PlaidNox Security Team
Originally published June 2025