DNS rebinding is one of those attacks that sounds almost too simple to work — and that’s exactly why it’s stuck around for over two decades. I still see it show up in bug bounty reports against internal APIs, IoT devices, and even developer tools that bind a web server to localhost without expecting a browser to be tricked into “legitimately” talking to it. This guide walks through exactly how the technique works, how to build and test a minimal rebinding server yourself in a lab, the tooling ecosystem around it, and how to actually defend against it.
What Is DNS Rebinding?
DNS rebinding is a technique that abuses the way browsers enforce the Same-Origin Policy (SOP) — based on hostname, not IP address — combined with the fact that DNS records can have very short time-to-live (TTL) values and can change between successive lookups for the same hostname. An attacker controls a DNS server that first answers queries for attacker.example with the attacker’s own IP address (so the victim’s browser can load a page and pass same-origin checks), and then, after a short TTL expires, starts answering the same hostname with a different IP — often an internal, private, or otherwise restricted address like 127.0.0.1 or a device on the victim’s LAN. Because the browser considers “same origin” to mean “same hostname,” it will happily let JavaScript already running from attacker.example make requests that now land on that second, rebound IP address — bypassing SOP protections that were supposed to prevent exactly this kind of cross-origin access.
Why This Isn’t Just a Theoretical Bug
This isn’t a single software vulnerability — it’s a structural weakness in how DNS and browser origin policy interact, and it’s been repeatedly rediscovered and re-weaponized:
- 2007 — Dan Kaminsky and others demonstrated DNS rebinding against Java applets and Flash.
- 2010s — renewed interest as researchers demonstrated it against home routers, printers, and other LAN-connected devices with unauthenticated web management interfaces.
- Present day — DNS rebinding remains a live concern for local developer tools (bundlers, debuggers, local AI/LLM tooling, dev servers) that bind to
localhostor0.0.0.0and trust “same-origin” requests without additional authentication, since a malicious webpage can rebind to127.0.0.1and talk to them directly.
The Core Mechanism, Step by Step
- The attacker registers a domain (e.g.,
evil-rebind.example) and configures a custom authoritative DNS server for it — not a normal hosting provider’s DNS, since the responses need to change dynamically and use very short TTLs. - The victim visits
http://evil-rebind.example/in their browser. The attacker’s DNS server answers with the attacker’s own real IP address, with a very short TTL (often 0 or 1 second). - The victim’s browser loads the attacker’s page, which includes JavaScript designed to make further requests back to
evil-rebind.exampleafter a short delay. - Because the TTL was so short, the browser (or the OS resolver) is forced to look up
evil-rebind.exampleagain for the next request. This time, the attacker’s DNS server answers with a different IP — typically127.0.0.1, a private RFC1918 address, or a specific internal service IP. - The browser’s JavaScript, still believing it’s talking to the same origin (
evil-rebind.example), sends its request — which now actually lands on the victim’s local machine or internal network, past whatever network boundary was supposed to protect it. - If the target service (an internal API, an IoT device’s web UI, a local dev tool) doesn’t authenticate requests based on something other than “did this come from the right origin,” the attacker’s JavaScript can now read responses from — and sometimes issue commands to — a service it should never have been able to reach from a public webpage.
Building and Testing a Minimal Rebinding DNS Server (Lab Only)
To actually understand the mechanism, it helps to build the simplest possible version yourself. This was written and tested directly using Python’s dnslib library:
#!/usr/bin/env python3
"""
Minimal DNS rebinding demonstration server (lab/educational use only).
Serves a low-TTL A record that flips between a "safe" first IP and a
"target" second IP after the first query, to illustrate the core
mechanism DNS rebinding attacks rely on.
"""
from dnslib.server import DNSServer, DNSHandler, BaseResolver
from dnslib import RR, QTYPE, A
import time
FIRST_IP = "203.0.113.10" # attacker-controlled "safe looking" server (TEST-NET-3)
SECOND_IP = "192.0.2.55" # simulated "internal target" address (TEST-NET-1)
FLIP_AFTER_SECONDS = 3
start_time = time.time()
class RebindResolver(BaseResolver):
def resolve(self, request, handler):
reply = request.reply()
qname = request.q.qname
elapsed = time.time() - start_time
ip = FIRST_IP if elapsed < FLIP_AFTER_SECONDS else SECOND_IP
reply.add_answer(RR(qname, QTYPE.A, rdata=A(ip), ttl=1))
print(f"[{elapsed:.1f}s] Query for {qname} -> answering {ip}")
return reply
if __name__ == "__main__":
resolver = RebindResolver()
server = DNSServer(resolver, port=5354, address="127.0.0.1")
server.start_thread()
print("Rebind test DNS server running on 127.0.0.1:5354 (TTL=1s, flips after 3s)")
try:
while server.thread.is_alive():
time.sleep(1)
except KeyboardInterrupt:
server.stop()
Install the one dependency:
pip install dnslib --break-system-packages
Run it:
python3 rebind_test_server.py
Query it twice, a few seconds apart, exactly as a browser’s resolver would:
dig @127.0.0.1 -p 5354 rebindtest.local +short
# wait a few seconds
dig @127.0.0.1 -p 5354 rebindtest.local +short
Real, tested output confirming the rebind actually happens:
=== query 1 (should be FIRST_IP) ===
[1.7s] Query for rebindtest.local. -> answering 203.0.113.10
203.0.113.10
=== query 2, after TTL expiry + flip window (should be SECOND_IP) ===
[5.7s] Query for rebindtest.local. -> answering 192.0.2.55
192.0.2.55
The first lookup returned the “safe” address; after the 1-second TTL expired and the flip window passed, the exact same hostname resolved to a completely different address on the very next query. That’s the entire mechanism — everything else in a real attack (the JavaScript payload, the target-scanning logic, the exploitation of whatever’s listening on the rebound IP) is built on top of this basic primitive.
Existing Public Tooling and Frameworks
Rather than building everything from scratch, several purpose-built frameworks exist for real assessments:
- Singularity of Origin (NCC Group) — a complete DNS rebinding attack framework with a custom rebinding DNS server, an attack automation/scanning component to find vulnerable internal services, and a “Hook and Control” mode that turns a victim’s browser into an HTTP proxy for interactively exploring an internal network through it. Documented via DEF CON and BSidesLV talks by its authors.
- dns-rebind-toolkit (brannondorsey) — a front-end JavaScript toolkit specifically aimed at IoT devices (Google Home, Roku, Sonos, Philips Hue, etc.), using WebRTC to leak the victim’s private IP first, then brute-forcing likely LAN addresses via injected iframes once rebinding is achieved.
- dnsrebinder (saelo) — a lightweight Go-based rebinding DNS server where the desired IP sequence is encoded directly into the queried hostname (e.g.,
1337_d83ad02e_7f000001.dnsrebinder.example), avoiding the need for any server-side state. - rebindMultiA — implements a Windows-specific variant that abuses multi-A-record DNS responses and browser fallback behavior rather than relying on a TTL-based flip.
A Complete Attack Walkthrough (Conceptual, Authorized Testing Only)
Assume you’re authorized to test whether an internal admin panel bound to 192.168.1.5:8080 with no authentication is exploitable via rebinding from an external webpage:
- Set up a rebinding DNS server (using a framework like Singularity, or a variant of the minimal server above) that first resolves
attack.yourdomain.testto your own attacker-controlled web server. - Host a page at that address containing JavaScript that, after a short delay (long enough for the DNS TTL to expire), issues a
fetch()orXMLHttpRequestback tohttp://attack.yourdomain.test:8080/. - Configure the DNS server so that, by the time this second request’s DNS lookup happens,
attack.yourdomain.testresolves to192.168.1.5instead. - If the admin panel at
192.168.1.5:8080doesn’t check anything beyond “did this request arrive,” the victim’s browser — now believing it’s still talking toattack.yourdomain.test— actually delivers the request to the internal panel, and the response is readable by the attacker’s JavaScript (since, as far as the browser’s SOP is concerned, it’s the “same origin”).
This entire chain only works because the target service trusted network-layer positioning (only reachable from inside the LAN, or from localhost) instead of an actual authentication mechanism.
Real-World Use Cases (Authorized Testing Only)
1. Internal API and admin panel assessments Confirming whether internal-only services actually enforce authentication, or rely solely on “you can only reach this if you’re already inside the network” — a false assumption DNS rebinding directly disproves.
2. IoT and embedded device security testing IoT devices with unauthenticated local web management interfaces (a still-common pattern) are a classic rebinding target, since a device sitting on 192.168.x.x with no auth is exactly what tools like dns-rebind-toolkit are built to enumerate and exploit.
3. Local developer tool security review Testing whether a local dev server, debugger, or (increasingly relevant) locally-running AI/LLM tooling that binds to 127.0.0.1 properly validates request origin/authentication rather than trusting “it came from localhost.”
4. Cloud metadata service exposure In server-side contexts (SSRF-adjacent), rebinding has also been used to reach cloud instance metadata endpoints (e.g., 169.254.169.254) from server-side code that performs its own DNS resolution and doesn’t pin/validate resolved IPs.
How to Defend Against DNS Rebinding
1. Never trust request origin/network position alone. Any service — internal, local, or otherwise — that performs privileged actions should require actual authentication (tokens, session cookies with proper SameSite settings, mutual TLS, etc.), not just “the request arrived from an allowed network.”
2. Validate the Host header. Servers (especially local dev tools and internal services) should check that the Host header of incoming requests matches an expected value, and reject anything else — this is the single most effective and cheapest mitigation for locally-bound services.
3. DNS pinning / TTL enforcement. Some browsers and DNS resolvers implement “DNS pinning,” refusing to honor a changed IP for a hostname within a short window of the previous resolution, specifically to blunt rapid rebinding attacks — though this has historically had inconsistent and incomplete coverage across browsers.
4. Reject private/reserved IP ranges in DNS responses at the resolver level. Tools like dnsmasq support --stop-dns-rebind, which drops DNS responses that resolve public hostnames to private (RFC1918), loopback, or link-local addresses — directly closing off the most common rebinding target ranges at the network’s own resolver.
5. Use SameSite cookies and CORS carefully. While rebinding specifically bypasses SOP (not CORS or cookie scoping), properly configured cookie attributes and CORS policies reduce the practical impact even when rebinding succeeds.
Integration with Broader Testing Workflows
- Burp Suite/OWASP ZAP: used alongside rebinding frameworks to inspect and manipulate the actual HTTP requests/responses once a rebind lands on an internal target.
- Custom DNS servers (dnsmasq, DNSChef, BIND):
dnsmasq‘s--stop-dns-rebindis a direct, testable defensive control; DNSChef itself can be configured to demonstrate short-TTL response switching for internal testing/training, though purpose-built rebinding frameworks handle the precise timing logic more reliably for actual exploitation demos. - Browser DevTools / Network tab: essential for confirming exactly when a rebind occurred during testing, correlating the DNS TTL expiry with the browser’s actual re-resolution behavior.
Troubleshooting and Common Mistakes (When Testing Defensively)
- Rebind “doesn’t work” in modern browsers — many browsers and OS-level resolvers cache DNS more aggressively than the raw TTL suggests, or implement some form of DNS pinning; successful rebinding often requires precise timing and sometimes multiple attempts, and behavior varies meaningfully across Chrome, Firefox, and Safari.
- Target service seems reachable but returns nothing useful — check whether the service actually validates the
Hostheader (a properly defended target should reject the mismatched-looking request even after a successful rebind). - DNS server not actually being queried a second time — confirm your TTL is genuinely low and that intermediate resolvers (a corporate DNS forwarder, for example) aren’t overriding or caching beyond what you configured — this is one of the most common practical obstacles to reliable rebinding.
- Cross-browser inconsistency — always test against the specific browser(s) in scope, since DNS pinning and resolution caching behavior differs significantly between them.
Best Practices for Authorized Testing
- Only test DNS rebinding against systems and networks you own or have explicit written authorization to assess — this technique specifically exists to bypass boundaries other people rely on for security.
- Use clearly-scoped, non-production test domains and reserved/documentation IP ranges (like
TEST-NETblocks:192.0.2.0/24,198.51.100.0/24,203.0.113.0/24) when building demonstration environments, exactly as done in the tested example above. - Document the precise timing and browser/resolver combination used for any successful demonstration, since rebinding reliability is highly environment-dependent.
- When reporting findings, include both the rebinding mechanism used and, critically, the underlying authentication gap it exposed — the real fix is almost always “add proper authentication,” not “prevent DNS rebinding” in isolation.
FAQ
Is DNS rebinding still relevant given modern browser protections? Yes — while some mitigations exist (DNS pinning, private-range filtering in some resolvers), the underlying weakness (SOP based on hostname, not IP) hasn’t fundamentally changed, and it continues to be found against internal services, IoT devices, and local developer tooling.
Does HTTPS prevent DNS rebinding? Not by itself. If the attacker’s certificate is valid for the hostname being rebound (which it typically is, since it’s the attacker’s own domain), HTTPS doesn’t block the technique — TLS validates the domain name, not which IP address that name currently happens to resolve to.
Can DNS rebinding be used against server-side applications, not just browsers? Yes, in SSRF-adjacent scenarios where server-side code resolves a hostname, makes a decision based on that IP (e.g., an allow-list check), and then re-resolves the same hostname again to actually connect — a classic time-of-check/time-of-use (TOCTOU) gap that rebinding directly exploits.
Is using DNS rebinding tools illegal? The tools and technique are legal, publicly documented security research. Using them against systems, networks, or devices you don’t own or don’t have explicit written authorization to test is illegal in most jurisdictions.
What’s the single most effective fix for a locally-bound service? Validate the Host header against an explicit allow-list of expected values (and reject everything else) — it’s cheap, requires no external dependencies, and directly closes the gap that makes rebinding effective against locally-bound services.
Summary
DNS rebinding is a structural mismatch between how browsers define “same origin” (by hostname) and how DNS actually works (a hostname can point anywhere, and can change at will with a short enough TTL). It’s not a bug you patch once — it’s a design assumption (“network position implies trust”) that keeps getting rediscovered against new categories of software, from routers and IoT devices in the 2010s to local developer and AI tooling today. Understanding the mechanism — build a minimal rebinding server yourself, as demonstrated above, and you’ll see it in about forty lines of code — makes it much easier to recognize where your own services might be making the same flawed assumption.
References
- Original DNS rebinding research overview (Stanford): https://crypto.stanford.edu/dns/
- Singularity of Origin (NCC Group) GitHub repository: https://github.com/nccgroup/singularity
- dns-rebind-toolkit GitHub repository: https://github.com/brannondorsey/dns-rebind-toolkit
- dnsrebinder GitHub repository: https://github.com/saelo/dnsrebinder
- dnsmasq documentation on
--stop-dns-rebind: http://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html - OWASP overview of DNS rebinding as an SSRF-adjacent risk: https://owasp.org/www-community/attacks/DNS_Rebinding
