DNS Rebinding - Bypassing SSRF Protection

How DNS rebinding defeats IP-based SSRF filters.

Introduction

A common defense against SSRF is to resolve the target hostname, check the resulting IP, and reject anything that points at a private or internal address. It sounds solid until you remember one thing: the server resolves DNS at least twice, and nothing forces both lookups to return the same answer. DNS rebinding lives in that gap. Below I walk through how it works against a typical SSRF filter.

How DNS Rebinding Works

The idea is simple. You control a domain, and you make it resolve to different IPs on demand. When the server does its “is this a safe IP?” check, the domain answers with a harmless public address. A moment later, when the server actually sends the request, the same domain answers with an internal address. The check passes; the request still hits the internal target. This is a time-of-check to time-of-use (TOCTOU) bug applied to name resolution.

The Web Server’s Protection

Take a generic web app hosted on AWS at example.com. It fetches images from a user-supplied URL but tries to block SSRF by only allowing requests to non-private IPs. The relevant code looks like this:

import ipaddress
from urllib.parse import urlparse
import requests

def valid_ip(ip):
    try:
        result = ipaddress.ip_address(ip)
        return result==True
    except:
        return False

def get(url, recursive_count=0):
    r = requests.get(url)
    return r.text

app = Flask(__name__)

@app.route('/fetch-image', methods=['GET'])
def fetch_image():
    url = request.form.get('url')

    # DNS rebinding bypass
    if not valid_ip(urlparse(url).netloc):
        return "Access denied!"

    response = get(url)
    return response


The Bypass

Here’s how an attacker gets around the filter above.

The trick is to point the attacker-controlled domain at two IPs and let the resolver hand them out alternately. Add two A records for the domain:

Type    Hostname             Value
A       dr3dd.xyz            169.254.169.254
A       dr3dd.xyz            53.45.124.31

Now dr3dd.xyz resolves to both the internal metadata address (169.254.169.254) and an external address the attacker controls (53.45.124.31).

Exploiting the Web Server

With the records in place, the attacker sends the server a crafted URL, for example http://example.com/fetch-image?url=http://dr3dd.xyz/latest/meta-data/iam/security-credentials/testcreds.

The server runs its blacklist check first: valid_ip resolves dr3dd.xyz, gets 53.45.124.31, sees a public address, and allows the request. Then get is called, which resolves the domain again — and this time it comes back as 169.254.169.254. The actual request goes to the internal metadata endpoint.

The filter never had a chance. It validated one lookup and trusted a second one to match, so the server ends up fetching internal resources on the attacker’s behalf.

Getting the Flag

With the two resolutions swapping under it, the filter is bypassed and the request reaches the AWS metadata service. In this challenge that was enough to pull the credentials and grab the flag.

Mitigating DNS Rebinding

A few countermeasures make this attack much harder:

Resolve once, then use that IP: The core fix. Resolve the hostname a single time, validate the resulting IP, and then connect to that exact IP rather than resolving the name again. This closes the TOCTOU gap entirely.

Whitelist valid hostnames: Where possible, only allow requests to a known set of trusted hosts or addresses instead of trying to blacklist bad ones.

Validate the resolved IP properly: Check that the resolved address isn’t in any private, loopback, link-local, or cloud-metadata range — not just a naive “is it public” test.

Pin or cap TTLs: Rebinding relies on short TTLs to flip answers quickly. Enforcing a minimum TTL or caching resolutions blunts that.

Rate limiting and monitoring: Watch for and throttle bursts of outbound fetches from a single source, and log resolutions so repeated flips stand out.

Resolving the target once and connecting to that specific IP is the change that actually kills the attack; the rest is defense in depth.

Conclusion

DNS rebinding works because IP-based SSRF filters check the name at one moment and use it at another. Validate the IP you resolve and then talk to that IP directly, and the whole class of bypass disappears.