November 4, 2026
The Allowlist That Trusted a Name Instead of an Address: Bypassing IP Restrictions With DNSβ¦
An IP-based allowlist feels like one of the more solid, straightforward security controls available: a feature is restricted to onlyβ¦

By T4nv1
4 min read
An IP-based allowlist feels like one of the more solid, straightforward security controls available: a feature is restricted to only communicate with a specific, pre-approved set of destinations, checked before any connection is made. It's a reasonable control, and it's also one with a specific, well-understood weakness that depends entirely on a detail most implementations get wrong without realizing it β the moment between when a hostname is checked and when it's actually connected to is a gap, and DNS, unlike almost everything else in a request's lifecycle, is something the attacker's own infrastructure fully controls.
The target, which I'll call Pinehurst Analytics here per their program's terms, is a business dashboard platform offering a "data source connector" feature, letting customers configure the platform to periodically fetch data from a URL of their choosing β explicitly restricted, by design, to prevent that URL from pointing at internal infrastructure.
A Control That Looked Genuinely Solid at First
Testing the obvious cases first: pointing the connector directly at an internal IP address was rejected immediately, with a clear error indicating the destination had failed an internal-range check.
POST /api/connectors
{ "sourceUrl": "http://10.0.0.5/internal-data" }
β 400: Destination resolves to a restricted address rangePOST /api/connectors
{ "sourceUrl": "http://10.0.0.5/internal-data" }
β 400: Destination resolves to a restricted address rangeThat error message itself was informative β it confirmed the check was resolving the hostname and inspecting the resulting IP address, which is the correct general approach, rather than merely pattern-matching against the literal string in the URL. This is a meaningfully more robust control than many of the naive, string-based blocklists I've bypassed on other targets. The actual question was whether that resolution happened once, at validation time, and was then trusted for the rest of the connector's lifetime, or whether it was re-verified at the moment the connector actually fetched data.
Why a Validated Hostname Isn't a Validated Connection
DNS resolution isn't a fixed, one-time fact about a domain name β it's a live lookup, and nothing stops a domain's DNS records from returning a different answer on a second query than they did on the first, especially if the attacker controls the authoritative DNS server for that domain and sets the record's time-to-live value to zero, forcing a fresh lookup on every single query rather than allowing any caching at all. If Pinehurst's connector validated the hostname's resolved IP once, when the connector was first configured, but then re-resolved that same hostname independently each time it actually fetched data on its periodic schedule, there was a real possibility the validation check and the actual fetch were looking at two different answers to the same question, separated by whatever time elapsed between configuration and the connector's next scheduled run.
Setting Up the Rebind
I registered a domain through a DNS provider allowing precise control over record TTLs and configured it to serve two different answers depending on timing: an immediate first resolution returning a harmless, legitimate public IP address I controlled, intended to pass Pinehurst's validation check cleanly, and a zero-TTL configuration ensuring any subsequent resolution of the same domain would trigger a fresh lookup rather than reusing a cached answer.
POST /api/connectors
{ "sourceUrl": "http://rebind-test.attacker-domain.com/data" }POST /api/connectors
{ "sourceUrl": "http://rebind-test.attacker-domain.com/data" }This passed validation, resolving at that moment to the legitimate public IP and clearing the internal-range check without issue. I then updated the DNS record to return an internal address instead, before the connector's next scheduled fetch was due to run.
Confirming the Fetch Followed the New Answer
Pinehurst's connectors ran on a periodic schedule, fetching from the configured source URL repeatedly over time rather than only once at setup β which meant I didn't need to race a narrow validation window at all; I simply needed the DNS record updated before whichever future fetch I wanted to target. When the next scheduled fetch ran, against a domain now resolving to an internal address I'd specified, the connector's own activity log β visible to me as the account owner, as a normal feature of the product β showed a fetch attempt against that internal address had occurred, with a connection timeout logged rather than a validation rejection, confirming the fetch itself performed its own, independent DNS resolution at request time rather than reusing or re-validating against the original, approved address.
Why a Timeout in the Log Was Still Conclusive Evidence
The specific internal address I'd pointed the second DNS answer at wasn't a live, listening service on Pinehurst's infrastructure, which is why the result was a connection timeout rather than any visible response data β I had no way to target a specific, known internal service without more information about their internal network layout, and guessing broadly felt like more invasive testing than the finding required. The timeout itself was sufficient: it proved the connector had accepted and attempted to connect to an internal-range address at fetch time, despite that same address range having been correctly rejected during the initial validation step, which is the entire vulnerability, fully demonstrated, without needing to actually reach a live internal service to make the case complete.
The Report
Title: DNS rebinding bypasses IP-range validation on the data source connector feature, allowing scheduled fetches against internal infrastructure
Root cause: The connector's destination validation resolves the configured hostname and checks the resulting IP address against a restricted-range blocklist at configuration time, but each subsequent scheduled fetch performs an independent DNS resolution without re-validating the result, allowing an attacker-controlled domain with a short TTL to pass validation with one IP address and later resolve to an internal, restricted address for the actual fetch.
Reproduction: The DNS rebinding setup including TTL configuration, the connector passing initial validation against a legitimate public IP, and the subsequent scheduled fetch's activity log showing a connection attempt against an internal address following the DNS record update.
Impact: An attacker able to configure a data source connector can cause the platform's own infrastructure to make outbound connection attempts against arbitrary internal addresses on an ongoing, scheduled basis, providing a persistent internal network access and mapping primitive that survives well past the original validation step.
Fix recommendations:
- Resolve the destination hostname and validate the resulting address immediately before each individual fetch, not only at configuration time, ensuring the address actually connected to is the one actually validated
- Pin the connection to the specific, validated IP address for that fetch rather than allowing a fresh DNS resolution to determine the actual connection target, closing the gap between validation and use entirely
- Apply the internal-range restriction at the network level as well, via egress filtering on the infrastructure actually making these outbound connector requests, as defense in depth independent of the application-level check
What Happened After
Pinehurst restructured the connector's validation to resolve and pin the destination address immediately before each fetch rather than relying on configuration-time validation alone, closing the specific timing gap this technique depended on.
Why DNS Rebinding Deserves Testing on Any Feature Validating a Hostname
Any feature performing a security check against a hostname's resolved IP address is worth testing specifically for the gap between when that resolution happens and when the actual connection occurs β particularly for features with a delay built into their normal operation, like scheduled fetches, webhooks, or anything triggered asynchronously after initial configuration, since that delay is exactly the window a zero-TTL DNS record is built to exploit.